Spinner Game Demo - TerryRitchie - 10-03-2024
UPDATE: I renamed all asset file names to lower case to work with Linux (thanks for the heads-up Dav). I also made a small change to the source code fixing an issue.
UPDATE: The ZIP below contains the new code and renamed asset files.
I took the arcade spinner code I wrote in another post and converted it to a library. Here is a demo program using that spinner code to control a spaceship around a perimeter on the screen.
Use the mouse to spin the ship around and the left mouse button to fire a bullet.
This is just a demo to see how well the spinner code works but is a good start to a game if someone wants to expand upon it. Someone in another thread was discussing a game that utilized enemy ships coming out of a worm hole or time tunnel. This would be a good start. I would continue work on it but I have way too much to work on with the game library currently.
The ZIP file below contains the assets (sound and image), libraries needed, and demo code.
Code: (Select All) OPTION _EXPLICIT
'Spinner game demo
'Game Library Variable Inclusions
'$INCLUDE:'lib_type_spoint.bi' TYPE TYPE_SPOINT SINGLE x,y point pair
'$INCLUDE:'lib_jpad_spinner.bi' JPAD_Spinner get degree of spinner
'$INCLUDE:'lib_img_introtate.bi' IMG_INTRotate() rotate an image
'$INCLUDE:'lib_math_deg2vec.bi' MATH_Deg2Vec() convert degree to vector
'$INCLUDE:'lib_math_distancep2p.bi' MATH_DistanceP2P() get distance of point to another point
CONST SWIDTH% = 800 ' width of screen
CONST SHEIGHT% = 600 ' height of screen
CONST MAXBULLETS% = 10 ' maximum number of bullets available
TYPE TYPE_BULLET ' BULLET PROPERTIES
InUse AS INTEGER ' array index in use
p AS TYPE_SPOINT ' bullet position
v AS TYPE_SPOINT ' bullet vector
Vel AS SINGLE ' bullet velocity
END TYPE
DIM Bullet(MAXBULLETS) AS TYPE_BULLET ' bullet array
DIM Center AS TYPE_SPOINT ' center point
DIM Degree AS INTEGER ' current spinner location
DIM ShipSheet AS LONG ' player ship sprite sheet
DIM Ship(-3 TO 3) AS LONG ' seven player ship images
DIM c AS INTEGER ' generic counter
DIM Bullets AS INTEGER ' total bullets flying on screen
DIM ShipRadius AS INTEGER ' radius of ship outer perimeter
DIM BulletRadius AS INTEGER ' radius of bullet outer perimeter
DIM SNDBullet AS LONG ' bullet sound
ShipSheet = _LOADIMAGE("shipsheet.png", 32) ' load player ship sprite sheet
SNDBullet = _SNDOPEN("bullet.ogg") ' load bullet sound
Center.x = SWIDTH \ 2 ' x center of screen
Center.y = SHEIGHT \ 2 ' y center of screen
ShipRadius = (MATH_SNGMin(SWIDTH, SHEIGHT) - 64) \ 2 ' ship outer perimeter radius
BulletRadius = ShipRadius - 38 ' bullet outer perimeter radius
' -----------------------------
'| Clip ship images from sheet |
' -----------------------------
FOR c = -3 TO 3 ' cycle through seven images
Ship(c) = _NEWIMAGE(64, 64, 32) ' create ship image canvas
_PUTIMAGE , ShipSheet, Ship(c), ((c + 3) * 64, 0)-((c + 3) * 64 + 63, 63) ' clip ship image from sprite sheet
NEXT c
' -----------------
'| Begin demo code |
' -----------------
SCREEN _NEWIMAGE(SWIDTH, SHEIGHT, 32) ' graphics window
_MOUSEHIDE ' hide the mouse pointer
DO ' begin spinner game demo loop
CLS ' clear screen
_LIMIT 60 ' 60 frames per second
Degree = JPAD_Spinner ' get spinner location
DrawShip Degree ' draw the player ship
IF _MOUSEBUTTON(1) THEN FireBullet Degree ' fire a bullet if player presses left mouse button
IF Bullets THEN UpdateBullets ' updates bullets if any flying
LOCATE 2, 2: PRINT "Use the mouse tospin ship around perimeter" ' print instructions
LOCATE 3, 2: PRINT "Left mouse button to fire"
LOCATE 5, 2: PRINT "Press ESC to exit"
_DISPLAY ' update screen with changes
LOOP UNTIL _KEYDOWN(27) ' leave demo when ESC pressed
' ------------------------
'| Asset cleanup and exit |
' ------------------------
FOR c = -1 TO 3 ' cycle through seven images
_FREEIMAGE Ship(c) ' remove ship image from RAM
NEXT c
_SNDCLOSE SNDBullet ' remove bullet sound from RAM
SYSTEM ' return to the operating system
' ---------------
'| End demo code |
' ---------------
'------------------------------------------------------------------------------------------------------------------------------------------
SUB DrawShip (Degree AS INTEGER)
' ------------------------------------------------------
'| Draw ship on screen at given degree around perimeter |
'| |
'| Degree - position on ship perimeter |
' ------------------------------------------------------
SHARED Ship() AS LONG ' need access to ship images
SHARED Center AS TYPE_SPOINT ' need access to center point
SHARED ShipRadius AS INTEGER ' need access to ship perimeter radius
STATIC pDegree AS INTEGER ' previous ship degree
STATIC Tilt AS INTEGER ' ship tilt amount
STATIC Frame AS INTEGER ' frame counter
DIM rShip AS LONG ' rotated image of ship
DIM ShipDir AS SINGLE ' direction of ship travel around perimeter
ShipDir = SGN(MATH_ShortAngle(Degree, pDegree)) ' get direction of ship (-1 counter-clockwise, 1 clockwise, 0 still)
IF ShipDir THEN ' is ship moving?
Tilt = Tilt + ShipDir ' yes, tilt ship in direction of movement
IF Tilt < -3 THEN ' keep tilt value between -3 and 3
Tilt = -3
ELSEIF Tilt > 3 THEN
Tilt = 3
END IF
Frame = 0 ' reset frame counter
ELSE ' no, ship is standing still
IF Tilt THEN ' is ship tilted?
Frame = Frame + 1 ' yes, increment frame counter
IF Frame = 4 THEN ' have 4 frames gone by?
Tilt = Tilt - SGN(Tilt) ' yes, tilt ship back toward center
Frame = 0 ' reset frame counter
END IF
END IF
END IF
rShip = _COPYIMAGE(Ship(Tilt)) ' get ship image
IMG_INTRotate rShip, MATH_FixDegree(Degree - 180) ' rotate ship image
_PUTIMAGE (Center.x + MATH_SIN(Degree) * ShipRadius - _WIDTH(rShip) \ 2,_
Center.y - MATH_COS(Degree) * ShipRadius - _HEIGHT(rShip) \ 2), rShip ' draw ship
_FREEIMAGE rShip ' ship image no longer needed
pDegree = Degree ' remember previous ship degree
END SUB
'------------------------------------------------------------------------------------------------------------------------------------------
SUB FireBullet (Degree AS INTEGER)
' -----------------------------------------
'| Adds a bullet to the bullet array |
'| |
'| Degree - origin degree around perimeter |
' -----------------------------------------
SHARED Bullet() AS TYPE_BULLET ' need access to bullet array
SHARED Bullets AS INTEGER ' need access to number of bullets flying
SHARED Center AS TYPE_SPOINT ' need access to center point
SHARED BulletRadius AS INTEGER ' need access to bullet origin radius
SHARED SNDBullet AS LONG ' need access to bullet sound
STATIC ShotTimer AS INTEGER ' time (frames) between bullets
DIM b AS INTEGER ' bullet counter
DIM i AS INTEGER ' free array index
IF Bullets = MAXBULLETS THEN EXIT SUB ' leave if maximum bullets flying
IF ShotTimer THEN ' ok to fire another bullet?
ShotTimer = ShotTimer - 1 ' no, decrement shot timer
IF ShotTimer THEN EXIT SUB ' leave if time still left on shot timer
END IF
Bullets = Bullets + 1 ' increment number of bullets flying
ShotTimer = 5 ' reset shot timer
_SNDPLAYCOPY SNDBullet ' play bullet sound
' ----------------------
'| Get free array index |
' ----------------------
b = 1 ' reset bullet counter
DO ' begen bullet loop
IF Bullet(b).InUse = 0 THEN i = b ' use this array index if not in use
b = b + 1 ' increment bullet counter
LOOP UNTIL i ' leave when free array index found
' --------------------------
'| Set up bullet parameters |
' --------------------------
Bullet(i).InUse = -1 ' mark this array index in use
Bullet(i).p.x = Center.x + MATH_SIN(Degree) * BulletRadius ' x location of bullet
Bullet(i).p.y = Center.y - MATH_COS(Degree) * BulletRadius ' y location of bullet
MATH_Deg2Vec MATH_FixDegree(Degree - 180), Bullet(i).v ' vector of bullet
END SUB
'------------------------------------------------------------------------------------------------------------------------------------------
SUB UpdateBullets ()
' --------------------------------------
'| Updates any flying bullets on screen |
' --------------------------------------
SHARED Bullet() AS TYPE_BULLET ' need access to bullet array
SHARED Bullets AS INTEGER ' need access to number of bullets flying
SHARED Center AS TYPE_SPOINT ' need access to center point
SHARED BulletRadius AS INTEGER ' need access to bullet origin radius
DIM b AS INTEGER ' bullet counter
DIM d AS SINGLE ' distance of bullet to center point
DIM c AS INTEGER ' brightness of bullet
DIM clr AS _UNSIGNED LONG ' color of bullet
b = 1 ' reset bullet counter
DO ' begin bullet loop
IF Bullet(b).InUse THEN ' is this bullet in use?
Bullet(b).p.x = Bullet(b).p.x + Bullet(b).v.x * Bullet(b).Vel ' yes, update x coordinate
Bullet(b).p.y = Bullet(b).p.y + Bullet(b).v.y * Bullet(b).Vel ' update y coordinate
d = MATH_DistanceP2P(Bullet(b).p, Center) ' distance of bullet to center
IF d < 1 THEN ' has bullet reached center?
Bullet(b).InUse = 0 ' yes, bullet no longer flying
Bullets = Bullets - 1 ' decrement total bullets flying
ELSE ' no, bullet still heading toward center
Bullet(b).Vel = MATH_Map(d, 0, BulletRadius, 1, 10) ' update velocity of bullet
c = MATH_Map(d, 0, BulletRadius, 96, 255) ' brightness level of bullet
clr = _RGB32(c, c, 0) ' color of bullet
CIRCLE (Bullet(b).p.x, Bullet(b).p.y), Bullet(b).Vel, clr ' draw bullet
PAINT (Bullet(b).p.x, Bullet(b).p.y), clr, clr ' paint bullet
END IF
END IF
b = b + 1 ' increment bullet counter
LOOP UNTIL b > MAXBULLETS ' leave when all bullets updated
END SUB
'Game Library Subroutine/Function Inclusions
'$INCLUDE:'lib_jpad_spinner.bm' JPAD_Spinner() get degree of spinner
'$INCLUDE:'lib_img_introtate.bm' IMG_INTRotate() rotate an image
'$INCLUDE:'lib_math_fixdegree.bm' MATH_FixDegree() keep degree within 0 to 359.999...
'$INCLUDE:'lib_math_deg2vec.bm' MATH_Deg2Vec() convert degree to vector
'$INCLUDE:'lib_math_distancep2p.bm' MATH_DistanceP2P() get distance of point to another point
'$INCLUDE:'lib_math_sngmin.bm' MATH_SNGMin() get minimum SINGLE value
'$INCLUDE:'lib_math_map.bm' MATH_Map() map one number system to another
'$INCLUDE:'lib_math_shortangle.bm' MATH_ShortAngle() get shortest angle between two angles
RE: Spinner Game Demo - RokCoder - 10-03-2024
This is really cool and reminds me very much of a game I played as a kid. I wish I could remember what that game was. It was either in the arcades or on a BBC Microcomputer. Probably the latter...
RE: Spinner Game Demo - TerryRitchie - 10-03-2024
(10-03-2024, 09:32 PM)RokCoder Wrote: This is really cool and reminds me very much of a game I played as a kid. I wish I could remember what that game was. It was either in the arcades or on a BBC Microcomputer. Probably the latter... Tempest from the arcades is the one I think about. That's a line vector game though.
RE: Spinner Game Demo - Dav - 10-03-2024
This works really good, Terry! I had to rename all the included files to lowercase under Linux first, but after that it ran fine. I also remember a game sorta like this from my arcade days.
- Dav
RE: Spinner Game Demo - TerryRitchie - 10-03-2024
(10-03-2024, 10:12 PM)Dav Wrote: This works really good, Terry! I had to rename all the included files to lowercase under Linux first, but after that it ran fine. I also remember a game sorta like this from my arcade days.
- Dav
Crap, I always forget about letter case when it comes to Linux. Sorry about that.
Also, in the top post I noted a change that should be made.
RE: Spinner Game Demo - Dav - 10-03-2024
No problem, I just put all the files into a folder, dropped down to it and did this command: rename 'y/A-Z/a-z/' *
This kind of thing helps me learn linux commands more, so I actually am glad it happened.
- Dav
RE: Spinner Game Demo - TerryRitchie - 10-03-2024
(10-03-2024, 10:22 PM)Dav Wrote: No problem, I just put all the files into a folder, dropped down to it and did this command: rename 'y/A-Z/a-z/' *
This kind of thing helps me learn linux commands more, so I actually am glad it happened.
- Dav I just renamed all the files to lower case for any other Linux user. Hey, I wonder if a command like that exists in Windows? I just went through all the files on the command line and renamed them all by hand, LOL.
The ZIP file and code in the original post has been updated. Thanks again for the Linux heads-up. I need to remember those things.
RE: Spinner Game Demo - Pete - 10-04-2024
What's a "tospin ship?"
You need to spend less time around the wife and more time at the space bars.
Pete
- Coding's a breeze. Typing's a bitch.
RE: Spinner Game Demo - TerryRitchie - 10-04-2024
(10-04-2024, 12:52 AM)Pete Wrote: What's a "tospin ship?"
You need to spend less time around the wife and more time at the space bars.
Pete
- Coding's a breeze. Typing's a bitch. oops
RE: Spinner Game Demo - JRace - 10-04-2024
Gyruss!
An old coin-op game that has a similar looking ship moving in the same way. That "where have I played this before?" feeling bugged me. As a proud old arcade regular, I had to figure it out.
I knew it began with a G!
Quote:I just renamed all the files to lower case for any other Linux user. Hey, I wonder if a command like that exists in Windows?
Not such a simple way, unless Win11 added features to RENAME. There are many free bulk file renaming utilities, and many file managers such as Free Commander can do bulk renaming with case changes.
Here is a way to change uppercase to lowercase (but not lower-to-upper) from the Windows command line, without additional tools:
Code: (Select All) for /f "Tokens=*" %f in ('dir /l/b/a-d') do (rename "%f" "%f")
if typed directly into the command prompt, or
Code: (Select All) for /f "Tokens=*" %%f in ('dir /l/b/a-d') do (rename "%%f" "%%f")
if used in a batch script.
It can also be done in PowersHell:
Code: (Select All) dir MYDIR -r | % { if ($_.Name -cne $_.Name.ToLower()) { ren $_.FullName $_.Name.ToLower() } }
(replace MYDIR with the name of the directory that contains the offending files, or leave it out to operate on the current directory. This method will recurse into subdirectories as well.)
Cool ship you've got there, Terry!
|