06-28-2003, 11:07 PM
Let's write a simple game in 1 hour. This is mine:
Tell me what you think
Code:
' Compile w/ ffix for maximum performance.
DECLARE SUB Advance (GfxObj AS ANY)
DECLARE SUB ObjDraw (GfxObj AS ANY, Tri() AS ANY)
DECLARE FUNCTION FindEmptyIndex% (Array() AS ANY)
PRINT "Easy PQB Asteroids (C) 28/6/2003 by Na Than Assh Antti."
PRINT "Coded in 1 hour, probably slow (SCREEN 7 stuff)."
PRINT : PRINT "Keys: LEFT CTRL and ALT: Rotate left and right."
PRINT " LEFT SHIFT: Advance."
PRINT " RIGHT SHIFT: Fire."
PRINT : PRINT "Any key to play..."
SLEEP: k$ = INKEY$
CONST PI = 3.141516916#
TYPE ObjectData
x AS SINGLE
y AS SINGLE
v AS SINGLE
angle AS SINGLE
state AS INTEGER
radius AS SINGLE
END TYPE
TYPE Points
x AS SINGLE
y AS SINGLE
END TYPE
' Define our ship (triangle). It is centered in the origin:
DIM GfxShip(2) AS Points
GfxShip(0).x = 5: GfxShip(0).y = 0
GfxShip(1).x = -5: GfxShip(1).y = 5
GfxShip(2).x = -5: GfxShip(2).y = -5
' Asteroids:
DIM GfxAst0(6) AS Points
DIM GfxAst1(6) AS Points
DIM GfxAst2(6) AS Points
' Big asteroid:
GfxAst0(0).x = 17: GfxAst0(0).y = 0
GfxAst0(1).x = 5: GfxAst0(1).y = 12
GfxAst0(2).x = -8: GfxAst0(2).y = 7
GfxAst0(3).x = -19: GfxAst0(3).y = -1
GfxAst0(4).x = -5: GfxAst0(4).y = -4
GfxAst0(5).x = -2: GfxAst0(5).y = -13
GfxAst0(6).x = 3: GfxAst0(6).y = -4
' Mid asteroid:
FOR i% = 0 TO 6
GfxAst1(i%).x = GfxAst0(i%).x * .75
GfxAst1(i%).y = GfxAst0(i%).y * .75
NEXT i%
' Small asteroid:
FOR i% = 0 TO 6
GfxAst2(i%).x = GfxAst0(i%).x * .5
GfxAst2(i%).y = GfxAst0(i%).y * .5
NEXT i%
DIM MyShip AS ObjectData
MyShip.x = 160
MyShip.y = 100
MyShip.v = 2
MyShip.angle = 0!
DIM Asteroids(100) AS ObjectData
FOR i% = 0 TO 9
Asteroids(i%).x = INT(RND * 320)
Asteroids(i%).y = INT(RND * 200)
Asteroids(i%).v = RND * 3 + 1
Asteroids(i%).angle = RND * PI
Asteroids(i%).radius = 12
Asteroids(i%).state = 0 ' Big asteroids
NEXT i%
FOR i% = 10 TO 100
Asteroids(i%).state = -1 ' Not used
NEXT i%
DIM Shoots(3) AS ObjectData
FOR i% = 0 TO 3: Shoots(i%).state = -1: NEXT i%
SCREEN 7, , 1, 0
DEF SEG = 0
FirePressed% = 0
Score% = 0
FlipFlop% = 0
FirstTime% = -1
WHILE INP(&H60) <> 1
' Create Asteroids?
IF (Score% > 0 AND (Score% MOD 2100 = 0)) OR FirstTime% THEN
FirstTime% = 0
FOR i% = 0 TO 9
Asteroids(i%).x = INT(RND * 320)
Asteroids(i%).y = INT(RND * 200)
Asteroids(i%).v = RND * 3 + 1
Asteroids(i%).angle = RND * PI
Asteroids(i%).radius = 12
Asteroids(i%).state = 0 ' Big asteroids
NEXT i%
FOR i% = 10 TO 100
Asteroids(i%).state = -1 ' Not used
NEXT i%
END IF
k$ = INKEY$ ' clear buffer
' Move Player:
IF PEEK(1047) AND 4 THEN
MyShip.angle = MyShip.angle - .1: IF MyShip.angle < 0 THEN MyShip.angle = 2 * PI
END IF
IF PEEK(1047) AND 8 THEN
MyShip.angle = MyShip.angle + .1: IF MyShip.angle > 2 * PI THEN MyShip.angle = 0
END IF
IF PEEK(1047) AND 2 THEN Advance MyShip
IF PEEK(1047) AND 1 THEN
IF NOT FirePressed% THEN
idx% = FindEmptyIndex%(Shoots())
IF idx% <> -1 THEN
Shoots(idx%).state = 0
Shoots(idx%).x = MyShip.x
Shoots(idx%).y = MyShip.y
Shoots(idx%).angle = MyShip.angle
Shoots(idx%).v = 4
END IF
END IF
FirePressed% = -1
ELSE
FirePressed% = 0
END IF
IF MyShip.x < 0 THEN MyShip.x = 319
IF MyShip.x > 319 THEN MyShip.x = 0
IF MyShip.y < 0 THEN MyShip.y = 199
IF MyShip.y > 199 THEN MyShip.y = 0
' Move Asteroids
FOR i% = 0 TO 100
FlipFlop% = NOT -ABS(SGN(FlipFlop%)) ' Flip the Flop.
IF Asteroids(i%).state <> -1 THEN
IF FlipFlop% THEN Advance Asteroids(i%)
IF Asteroids(i%).x < 0 THEN Asteroids(i%).x = 319
IF Asteroids(i%).x > 319 THEN Asteroids(i%).x = 0
IF Asteroids(i%).y < 0 THEN Asteroids(i%).y = 199
IF Asteroids(i%).y > 199 THEN Asteroids(i%).y = 0
' Collisions:
' 1.- With shoots
FOR j% = 0 TO 3
' Lame square checking (may this change??)
IF Shoots(j%).state <> -1 THEN
IF Shoots(j%).x > Asteroids(i%).x - Asteroids(i%).radius THEN
IF Shoots(j%).x < Asteroids(i%).x + Asteroids(i%).radius THEN
IF Shoots(j%).y > Asteroids(i%).y - Asteroids(i%).radius THEN
IF Shoots(j%).y < Asteroids(i%).y + Asteroids(i%).radius THEN
Shoots(j%).state = -1
' Break Asteroid:
IF Asteroids(i%).state < 2 THEN
mySt% = Asteroids(i%).state
xx% = Asteroids(i%).x
yy% = Asteroids(i%).y
vv! = Asteroids(i%).v
a! = Asteroids(i%).angle
Asteroids(i%).state = -1
idx1% = FindEmptyIndex%(Asteroids())
IF idx1% <> -1 THEN
Asteroids(idx1%).state = mySt% + 1
Asteroids(idx1%).x = xx%
Asteroids(idx1%).y = yy%
Asteroids(idx1%).v = vv!
Asteroids(idx1%).angle = a! + PI / 2
IF (mySt% + 1) = 1 THEN
Asteroids(idx1%).radius = 10
ELSE
Asteroids(idx1%).radius = 7
END IF
END IF
idx2% = FindEmptyIndex%(Asteroids())
IF idx2% <> -1 THEN
Asteroids(idx2%).state = mySt% + 1
Asteroids(idx2%).x = xx%
Asteroids(idx2%).y = yy%
Asteroids(idx2%).v = vv!
Asteroids(idx2%).angle = a! - PI / 2
IF (mySt% + 1) = 1 THEN
Asteroids(idx2%).radius = 10
ELSE
Asteroids(idx2%).radius = 7
END IF
END IF
Score% = Score% + 2 * (mySt% + 1)
ELSE
Asteroids(i%).state = -1 ' Break!
Score% = Score% + 50
END IF
END IF
END IF
END IF
END IF
END IF
NEXT j%
' 2.- With player
IF MyShip.x > Asteroids(i%).x - Asteroids(i%).radius THEN
IF MyShip.x < Asteroids(i%).x + Asteroids(i%).radius THEN
IF MyShip.y > Asteroids(i%).y - Asteroids(i%).radius THEN
IF MyShip.y < Asteroids(i%).y + Asteroids(i%).radius THEN
SCREEN 7, , 0, 0
t$ = "FINAL SCORE:" + STR$(Score%)
LOCATE 12, 20 - LEN(t$) \ 2: PRINT t$
WHILE k$ <> INKEY$: WEND
SLEEP: k$ = INKEY$
FirstTime% = -1: Score% = 0
SCREEN 7, , 1, 0
END IF
END IF
END IF
END IF
END IF
NEXT i%
' Move Shoots
FOR i% = 0 TO 3
IF Shoots(i%).state <> -1 THEN
Advance Shoots(i%)
IF Shoots(i%).x < 0 OR Shoots(i%).x > 319 OR Shoots(i%).y < 0 OR Shoots(i%).y > 199 THEN Shoots(i%).state = -1
END IF
NEXT i%
' Render:
LINE (0, 0)-(319, 199), 0, BF
ObjDraw MyShip, GfxShip()
FOR i% = 0 TO 100
SELECT CASE Asteroids(i%).state
CASE 0:
ObjDraw Asteroids(i%), GfxAst0()
CASE 1:
ObjDraw Asteroids(i%), GfxAst1()
CASE 2:
ObjDraw Asteroids(i%), GfxAst2()
END SELECT
NEXT i%
FOR i% = 0 TO 3
IF Shoots(i%).state <> -1 THEN
PSET (Shoots(i%).x, Shoots(i%).y), 15
END IF
NEXT i%
LOCATE 1, 1: PRINT Score%
WAIT &H3DA, 8, 8: WAIT &H3DA, 8
PCOPY 1, 0
WEND
SUB Advance (GfxObj AS ObjectData)
GfxObj.x = GfxObj.x + GfxObj.v * COS(GfxObj.angle)
GfxObj.y = GfxObj.y + GfxObj.v * SIN(GfxObj.angle)
END SUB
FUNCTION FindEmptyIndex% (Array() AS ObjectData)
res% = -1
FOR i% = 0 TO UBOUND(Array)
IF Array(i%).state = -1 THEN res% = i%: EXIT FOR
NEXT i%
FindEmptyIndex% = res%
END FUNCTION
SUB ObjDraw (GfxObj AS ObjectData, Tri() AS Points)
' Draws a rotated closed polygon. It uses the typlica matrix transform
' for 2D
oldxx% = 0: oldyy% = 0
FOR i% = 0 TO UBOUND(Tri)
' Rotate points
xx% = INT(Tri(i%).x * COS(GfxObj.angle) - Tri(i%).y * SIN(GfxObj.angle))
yy% = INT(Tri(i%).x * SIN(GfxObj.angle) + Tri(i%).y * COS(GfxObj.angle))
IF i% > 0 THEN
LINE (GfxObj.x + oldxx%, GfxObj.y + oldyy%)-(GfxObj.x + xx%, GfxObj.y + yy%)
ELSE
' First point: no line to draw. Instead, we remember it to
' close the polygon after the loop ends.
initxx% = xx%: inityy% = yy%
END IF
oldxx% = xx%
oldyy% = yy%
NEXT i%
LINE (GfxObj.x + oldxx%, GfxObj.y + oldyy%)-(GfxObj.x + initxx%, GfxObj.y + inityy%)
END SUB
Tell me what you think