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
|