defender type screen wrap

Blitz3D Forums/Blitz3D Beginners Area/defender type screen wrap

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

I have written a small demo here that uses a technique similar to what Anthony describes. Well I guess the idea is the same on some level, while coding I noticed that this can indeed be quite tricky to figure out. Using a piece of paper and a pen really helps, and even then you have to turn the music off (well I had to).

The important code is in the main function. It checks if a ship is close enough to the player, if so it is drawn. This is the normal case. If the difference between the two is big however, it could be that it is so big because they are both near the edge of the world, on opposite sides. This means they are in fact *close* to each other as the world wraps around! So, if the difference is *big enough*, the ship is also drawn.

In that last case you have to do a bit more work to compute *where* to draw the ship on the screen ("drawOffset"); my program uses 2 different computations based on whether the ship is to the right or to the left of the player.

To be able to see what is going on I added a radar, just like in Defender (more or less). This is really necessary to check if everything works as intended. ;) The three lines on the radar represent the area you can see; the center line is the player position. Reminds me of Falcon Patrol II too... ti ti ti ti de li tiii, ti de li etc. The player moves to the right automatically.

; #########
; constants
; #########

Const SCREENWIDTH  = 800
Const SCREENHEIGHT = 600
Const WORLDWIDTH   = 3500
Const SHIPCOUNT    = 20
Const SCROLLSPEED  = 2


; ######################
; program initialization
; ######################

Graphics(SCREENWIDTH,SCREENHEIGHT)
SetBuffer(BackBuffer())
SeedRnd(MilliSecs())


; #######
; globals
; #######

Global g_playerX


; #########
; SHIP type
; #########

Type SHIP
	Field f_x
	Field f_y
End Type


; ######################
; radar drawing function
; ######################

Function drawRadar()
	; draw radar background
	Color(0,0,200)	
	Rect(0,0,WORLDWIDTH/10,SCREENHEIGHT/10,True)
	
	; plot ships
	Color(255,255,255)
	For ship.SHIP = Each SHIP
		Plot(ship\f_x/10,ship\f_y/10)
	Next
	
	; plot line at player position
	Color(200,200,200)
	Line(g_playerX/10,0,g_playerX/10,SCREENHEIGHT/10)
	
	; compute left and right screen border position, maybe wrap
	leftBorder = g_playerX-SCREENWIDTH/2
	If (leftBorder < 0) Then
		leftBorder = leftBorder + WORLDWIDTH
	End If
	rightBorder = g_playerX+SCREENWIDTH/2
	If (rightBorder > WORLDWIDTH) Then
		rightBorder = rightBorder - WORLDWIDTH
	End If
	
	; draw left and right border on radar
	Color(175,175,175)
	Line(leftBorder/10,0,leftBorder/10,SCREENHEIGHT/10)
	Line(rightBorder/10,0,rightBorder/10,SCREENHEIGHT/10)
End Function


; #################
; main program loop
; #################

; create ships first
For i = 1 To SHIPCOUNT
	ship.SHIP = New SHIP
	ship\f_x  = Rand(0,WORLDWIDTH)
	ship\f_y  = Rand(0,SCREENHEIGHT)
Next

; player starts in center of world
g_playerX = WORLDWIDTH/2

; loop until player presses escape
While(Not(KeyHit(1)))

	Cls

	; get screen position of player -> always center of screen
	drawPlayerX = SCREENWIDTH/2
	
	; draw line representing player
	Color(0,255,0)
	Line(drawPlayerX,0,drawPlayerX,SCREENHEIGHT)

	; draw ships
	Color(255,255,255)
	For ship.SHIP = Each SHIP
	
		; compute offset compared to player position (distance of going from player to ship)
		offset = ship\f_x - g_playerX
	
		; default is not to draw
		draw = False
		
		; if absolute difference is smaller than screen width...
		If (Abs(offset) <= SCREENWIDTH) Then
			
			; draw at offset
			drawOffset = offset
			draw       = True
		
		; if absolute difference is big enough so that wrapping occurs...
		Else If (Abs(offset) > (WORLDWIDTH-SCREENWIDTH)) Then
		
			; compute drawing-offset based on player position and ship position
			If (ship\f_x > g_playerX) Then
				drawOffset = -g_playerX - (WORLDWIDTH-ship\f_x)
			Else
				drawOffset = ship\f_x + (WORLDWIDTH-g_playerX)
			End If
			draw = True
		
		End If
		
		; finally, draw (if visible) using computed drawing-offset
		If (draw) Then
			Oval(drawPlayerX+drawOffset,ship\f_y,5,5,True)	
		End If
	Next
	
	; draw the radar
	drawRadar()
	
	Flip

	; move the player to the right, maybe wrap
	g_playerX = g_playerX + SCROLLSPEED
	If (g_playerX > WORLDWIDTH) Then
		g_playerX = 0
	End If
Wend

Delete Each SHIP

End