Conversion of Waponez II, the PureBASIC example to BlitzMax NG

Started by SToS, November 14, 2024, 12:36:54

Previous topic - Next topic

SToS

As a learning exercise, here's my attempt at converting the PureBASIC example Waponez II to BlitzMax NG.

Built and tested under Linux only, see attachment for source + data.

I find the process of converting examples the best way to learn a new languages syntax.

Due credit goes to original authors NC-Gamez for the Amiga version and graphics from the AMOS banks, not sure who the PureBASIC code belongs to.

SuperStrict

?win32
Framework SDL.d3d9sdlmax2d
?Not win32
Framework SDL.gl2sdlmax2d
?
'Framework SDL.SDLRenderMax2D
Import SDL.SDLFreeAudio
Import BRL.BmpLoader
Import BRL.WavLoader
Import BRL.FreeAudioAudio
Import BRL.Random

SetAudioDriver("FreeAudio SDL")

Type TEntity
Field x:Int
Field y:Int
Field w:Int
Field h:Int
Field image:Int
Field speed_x:Int
Field speed_y:Int
End Type

Type TPlayer Extends TEntity
    Field dead:Int
    Field dead_delay:Int
End Type

Global player:TPlayer

Type TBullet Extends TEntity
End Type

Global bullet_list:TList = CreateList()

Type TExplosion
Field x:Int
Field y:Int
Field state:Int
Field retard:Int
End Type

Global explosion_list:TList = CreateList()

Type TAlien
Field x:Int
Field y:Int
Field w:Int
Field h:Int
Field speed:Int
Field start_image:Int
Field end_image:Int
Field image_delay:Int
Field next_image_delay:Int
Field actual_image:Int
Field armor:Int
End Type

Global alien_list:TList = CreateList()
   
Const DATA_PATH:String = "./Data/"
Const BULLET_SPEED:Int = 10

Global sprites:TImage[] = New TImage[100]
Global bullet_delay:Int = 10
Global alien_delay:Int = 0
Global boss:Int = 0
Global scroll_y:Int = 0
Global scroll_delay:Int = 0
Global score:Int = 0

Graphics 640, 480, 0
HideMouse
SeedRnd(MilliSecs())

'
' Load the sound effects
'
 
Global sound_lazer:TSound     = LoadSound(DATA_PATH + "Lazer.wav")
Global sound_explosion:TSound = LoadSound(DATA_PATH + "Explosion.wav")
   
'
' Load the 3 player sprites
'
sprites[3] = LoadImage(DATA_PATH + "Player_1.bmp")  
sprites
 = LoadImage(DATA_PATH + "Player_2.bmp")  
sprites[2] = LoadImage(DATA_PATH + "Player_3.bmp")  
'
' Load the bullets
'
sprites[4] = LoadImage(DATA_PATH + "Bullet_1.bmp")  
sprites[6] = LoadImage(DATA_PATH + "Bullet_Right.bmp")  
sprites[7] = LoadImage(DATA_PATH + "Bullet_Left.bmp")  
sprites[8] = LoadImage(DATA_PATH + "Bullet_Diag1.bmp")  
sprites[9] = LoadImage(DATA_PATH + "Bullet_Diag2.bmp")  
sprites[55] = LoadImage(DATA_PATH + "Bullet_Bottom.bmp")  
'
' Sprite 10 To 15 reserved For the rotating animated alien..
'
For Local k:Int = 0 To 5
sprites[k + 10] = LoadImage(DATA_PATH + "Enemy_3_" + String.FromInt(k + 1) + ".bmp")
Next k
 
'
' Sprite 20 To 30 reserved For the explosions...
'
For Local k:Int = 0 To 7
    sprites[k + 20] = LoadImage(DATA_PATH + "Explosion_" + String.FromInt(k + 1) + ".bmp")
Next k
   
'
' Load the background sprite
'
sprites[30] = LoadImage(DATA_PATH + "Back_3.bmp")
 
'
'
'
 
player.image = 3
player.speed_x = 6
player.speed_y = 6
player.x = 300
player.y = 400
player.dead = 0
player.dead_delay = 0
player.w = ImageWidth(sprites[3])
player.h = ImageHeight(sprites[3])
Repeat
' Draw the background (a unified one...)
   
    For Local x:Int = 0 To 640 Step 32
      For Local y:Int = -32 To 480 Step 32
        DrawImage(sprites[30], x, y + scroll_y)
      Next
    Next
   
    CheckCollisions()
    MovePlayers()
    DisplayBullets()
    NewAlienWave()
    DisplayAliens()
    DisplayExplosions()
    If bullet_delay > 0
      bullet_delay :- 1
    EndIf
    If scroll_delay = 0
      scroll_y :+ 1
      scroll_delay = 0
    Else
      scroll_delay :- 1
    EndIf
   
    If scroll_y > 31
      scroll_y = 0
    EndIf   
Flip
Cls

Until KeyHit(KEY_ESCAPE)
End
Function AddBullet(sprite:Int, x:Int, y:Int, speed_x:Int, speed_y:Int)
Local bullet:TBullet = New TBullet
bullet.x       = x
bullet.y       = y
bullet.w       = ImageWidth(Sprites[sprite])
bullet.h       = ImageHeight(Sprites[sprite])
bullet.image   = sprite
bullet.speed_x = speed_x
bullet.speed_y = speed_y
ListAddLast(bullet_list, bullet)
End Function
Function MovePlayers()
player.image = 3 ' Non-moving player image
If KeyDown(KEY_LEFT) Then
player.x :- player.speed_x
player.image = 2 ' Left moving player image
EndIf
If KeyDown(KEY_RIGHT) Then
player.x :+ player.speed_x
player.image = 0' Right moving player image
EndIf
If KeyDown(KEY_UP) Then
player.y :- player.speed_y
EndIf
If KeyDown(KEY_DOWN) Then
player.y :+ player.speed_y
EndIf
If player.x < 0 Then
player.x = 0
EndIf
If player.y < 0 Then
player.y = 0
EndIf
If player.x > 640 - player.w Then
player.x = 640 - player.w
EndIf
If player.y > 480 - player.h Then
player.y = 480 - player.h
EndIf
If player.dead = 1 Then
Local explosion:TExplosion = New TExplosion
explosion.x = player.x
explosion.y = player.y
ListAddLast(explosion_list, explosion)
player.dead = 0
Else
If player.dead_delay > 0 Then
player.dead_delay :- 1
If player.dead_delay < 200 Then
                If player.dead_delay Mod 8 = 1 Then
SetBlend(LIGHTBLEND)
    DrawImage(sprites[player.image], player.x, player.y)
SetBlend(ALPHABLEND)
Else
    DrawImage(sprites[player.image], player.x, player.y)
                EndIf
EndIf
Else
DrawImage(sprites[player.image], player.x, player.y)
EndIf
EndIf
If KeyDown(KEY_SPACE) Then ' Or Fire
If bullet_delay = 0 Then
If player.dead_delay < 100 Then
bullet_delay = 10
' AddBullet() syntax: (#Sprite, x, y, SpeedX, SpeedY)
'
AddBullet( 4, player.x +  5, player.y - 10,  0           , -BULLET_SPEED) ' Front bullet (Double bullet sprite)
AddBullet( 6, player.x + 45, player.y +  6,  BULLET_SPEED,  0)            ' Right side bullet
AddBullet( 7, player.x - 11, player.y +  6, -BULLET_SPEED,  0)            ' Left side bullet
AddBullet( 8, player.x + 45, player.y -  6,  BULLET_SPEED, -BULLET_SPEED) ' Front-Right bullet
AddBullet( 9, player.x - 11, player.y -  6, -BULLET_SPEED, -BULLET_SPEED) ' Front-Left bullet
AddBullet(55, player.x + 20, player.y + 45,  0           ,  BULLET_SPEED) ' Rear bullet
  
PlaySound(sound_lazer) ' Play the 'pffffiiiouuu' laser like sound
EndIf
EndIf
EndIf
End Function
Function DisplayBullets()
For Local bullet:TBullet = EachIn bullet_list
If bullet.y < 0 Or bullet.x < 0 Or bullet.x > 640 - bullet.w Or bullet.y > 480 Then
ListRemove(bullet_list, bullet)
Else
DrawImage(sprites[bullet.image], bullet.x, bullet.y, 0)
bullet.x:+ bullet.speed_x
bullet.y:+ bullet.speed_y
EndIf 
Next
End Function
Function NewAlienWave()
If alien_delay = 0 Then
Local alien:TAlien = New TAlien
If boss = 1 Then
alien.x                = 100
alien.y                = -16
alien.w                = ImageWidth(sprites[50])
alien.h                = ImageHeight(sprites[50])
alien.speed            = 2
alien.start_image      = 50
alien.end_image        = 50
alien.image_delay      = 1
alien.next_image_delay = 1
alien.actual_image     = 50
alien.armor            = 20
 
alien_delay = 80
Else
alien.x                = Rand(0,600)
alien.y                = -32
alien.w                = ImageWidth(sprites[10])
alien.h                = ImageHeight(sprites[10])
alien.speed            = 3
alien.start_image      = 10
alien.end_image        = 15
alien.image_delay      = 4
alien.next_image_delay = alien.image_delay
alien.actual_image     = 10
alien.armor            = 5
   
alien_delay = Rand(0,20)
EndIf
ListAddLast(alien_list, alien)
Else
alien_delay :- 1
EndIf
End Function
Function DisplayAliens()
For Local alien:TAlien = EachIn alien_list
DrawImage(sprites[alien.actual_image], alien.x, alien.y, 0)
alien.y :+ alien.speed
If alien.next_image_delay = 0 Then
alien.actual_image :+ 1
If alien.actual_image > alien.end_image Then
alien.actual_image = alien.start_image
EndIf
alien.next_image_delay = alien.image_delay
Else
alien.next_image_delay :- 1
EndIf
If alien.armor <= 0 Then
Local explosion:TExplosion = New TExplosion
explosion.x = alien.x
explosion.y = alien.y
ListAddLast(explosion_list, explosion)
score :+ 20
ListRemove(alien_list, alien)
Else
If alien.y > 480 Then
ListRemove(alien_list, alien)
EndIf
EndIf
Next
End Function
'
Function CheckCollisions()
ResetCollisions()
For Local alien:TAlien = EachIn alien_list
For Local bullet:TBullet = EachIn bullet_list
If ImagesCollide(sprites[bullet.image], bullet.x, bullet.y, 0, sprites[alien.actual_image], alien.x, alien.y, 0) Then
alien.armor :- 1
ListRemove(bullet_list, bullet)
EndIf
Next
If player.dead_delay = 0 Then ' No more invincible...
If ImagesCollide(sprites[player.image], player.x, player.y, 0, sprites[alien.actual_image], alien.x, alien.y, 0) Then
player.dead = 1
player.dead_delay = 300
Local explosion:TExplosion = New TExplosion
explosion.x = alien.x
explosion.y = alien.y
ListAddLast(explosion_list, explosion)

ListRemove(alien_list, alien)
EndIf
EndIf
Next
End Function
Function DisplayExplosions()
For Local explosion:TExplosion = EachIn explosion_list
DrawImage(sprites[explosion.state + 20], explosion.x, explosion.y, 0)
If explosion.retard = 0 Then
If explosion.state = 0 Then ' Play the sound only at the explosion start.
PlaySound(sound_explosion)
EndIf
If explosion.state < 7 Then
explosion.state :+ 1
explosion.retard = 3
Else
ListRemove(explosion_list, explosion)
EndIf
Else
explosion.retard :- 1
EndIf
Next
End Function

Waponez II.zip

Midimaster

Do you want reviews or critiques? Or are you (final) happy with the current state of the code?
...back from North Pole.

SToS

Quote from: Midimaster on November 14, 2024, 12:48:13Do you want reviews or critiques? Or are you (final) happy with the current state of the code?
It was just a learning excercise that I actually got to work using the somewhat sparse Blitzmax documentation for some of its libraries.
I just thought it would be worth sharing for others who are trying to stitch working examples together using the poor documentation available.

Feel free to review/critique if you desire.  If the state of the code is "it works" then I'm happy ;D

Baggey

I had to change the Include to
QuoteImport BRL.RandomDefault
For it to run here.

Great effort! I wish more users would do this as BlitzMaxNG is a very Powerful Basic.

I to learn by example. By altering code like you have just produced.  ;)

Have fun with it, I wanna see more! ;D

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 32GB ram  2x1TB SSD and NVIDIA Quadro K1200 on Acer 24" . DID Technology stop! Or have we been assimulated!

Windows10, Parrot OS, Raspberry Pi Black Edition! , ZX Spectrum 48k, C64, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

Quote from: SToS on November 14, 2024, 13:08:22
Quote from: Midimaster on November 14, 2024, 12:48:13Do you want reviews or critiques? Or are you (final) happy with the current state of the code?
It was just a learning excercise that I actually got to work using the somewhat sparse Blitzmax documentation for some of its libraries.
I just thought it would be worth sharing for others who are trying to stitch working examples together using the poor documentation available.

Feel free to review/critique if you desire.  If the state of the code is "it works" then I'm happy ;D


QuoteI actually got it to work using the somewhat sparse Blitzmax documentation for some of its libraries.
I totally agree someone gave up or got bored doing it! :-X

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 32GB ram  2x1TB SSD and NVIDIA Quadro K1200 on Acer 24" . DID Technology stop! Or have we been assimulated!

Windows10, Parrot OS, Raspberry Pi Black Edition! , ZX Spectrum 48k, C64, Enterprise 128K, The SID chip. Im Misunderstood!

SToS

Quote from: Baggey on November 14, 2024, 13:13:28I had to change the Include to
QuoteImport BRL.RandomDefault
For it to run here.

Great effort! I wish more users would do this as BlitzMaxNG is a very Powerful Basic.

I to learn by example. By altering code like you have just produced.  ;)

Have fun with it, I wanna see more! ;D

Baggey
Cheers Baggey!

Out of interest, was your ammendment needed for a Windows build?


Baggey

Yes, Im running Windows 10. You on Linux or something!?

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 32GB ram  2x1TB SSD and NVIDIA Quadro K1200 on Acer 24" . DID Technology stop! Or have we been assimulated!

Windows10, Parrot OS, Raspberry Pi Black Edition! , ZX Spectrum 48k, C64, Enterprise 128K, The SID chip. Im Misunderstood!

SToS

Quote from: Baggey on November 14, 2024, 13:22:35Yes, Im running Windows 10. You on Linux or something!?
Linux (Debian 11/Bullseye) currently Blitzmax NG weekly version 0.143, but I see I'm a bit behind with the latest weekly build so just updating to 0.146 to see if it still works as is.

Derron

that brl.randomdefault is required for older NG releases, not the current weekly ones (where brl.randomdefault was removed again as "brl.random" was refactored and you have multiple other random number generators in the new module scope "random.mod")


The code looks quite tidy and runs out of the box in a rather new Linux NG setup.


Code like this: String.FromInt(k + 1)
surely comes from the translation to BlitzMax - but you might already know, that BlitzMax does not need that kind of translation when glueing together strings.
LoadImage(DATA_PATH + "Enemy_3_" + String.FromInt(k + 1) + ".bmp")
'could become
LoadImage(DATA_PATH + "Enemy_3_" + (k + 1) + ".bmp")

Another hint - for now you only react to "KEY_ESCAPE" to exit the game. I always add "AppTerminate()" to the until case - this way you can also close via the "[.x.]" button of the Window:

Until KeyHit(KEY_ESCAPE)
'becomes
Until KeyHit(KEY_ESCAPE) or AppTerminate()


all other comments I would be able to give would be improvements on the code base but I guess this is not the target of your excercise here.


bye
Ron



Baggey

@Derron 

Quotethat brl.randomdefault is required for older NG releases, not the current weekly ones (where brl.randomdefault was removed again as "brl.random" was refactored and you have multiple other random number generators in the new module scope "random.mod")


The code looks quite tidy and runs out of the box in a rather new Linux NG setup.

BlitzmaxNG with all these weekly builds is starting to end up like opensource stuff. Some run some don't. Keeping track of what's current or not. Unless there is an update Link to know what is the current download. This is going to happen more often :-X

Im not sure wether you can make this happen, but is there a guide to getting BlitzmaxNG working on Raspberry PI 400?

Sorry @SToS not trying to jump your thread. But im keen to see more stuff like this happen and get a broader base of BlitzmaxNG users. Cant wait to see you do more stuff! ;)

Kind Regards Baggey

Running a PC that just Aint fast enough!? i7 4Ghz Quad core 32GB ram  2x1TB SSD and NVIDIA Quadro K1200 on Acer 24" . DID Technology stop! Or have we been assimulated!

Windows10, Parrot OS, Raspberry Pi Black Edition! , ZX Spectrum 48k, C64, Enterprise 128K, The SID chip. Im Misunderstood!