That's right, I've been using Blitz3D for years and this is my first game (written in Blitzmax).
I originally started this so I could write a tutorial on how to make a simple Blitzmax game, but I realised I wasn't sure what I was doing when I began so I just finished it and may get around to writing a tutorial for it sometime.
It's a (very) simple sliding puzzle game.
image used
I originally started this so I could write a tutorial on how to make a simple Blitzmax game, but I realised I wasn't sure what I was doing when I began so I just finished it and may get around to writing a tutorial for it sometime.
It's a (very) simple sliding puzzle game.
Rem Spuzzle, a simple sliding tile, puzzle game based on the old plastic toys I used to have as a kid EndRem Strict Graphics 800,600,0 ' Windowed mode, 800x600 SeedRnd(MilliSecs()) Type TPoint Field X Field Y End Type Type TSpuzzleBoard Field Width : Int Field Height : Int Field TileWidth : Int Field TileHeight : Int Field Board : Int[][] 'an array of arrays, because we need the board size to be dynamically resized and 'you cannot use slices to dynamically resize multi-dimensional arrays. Field img : TImage Field Target:Int Field MoveCount:Int Field Difficulty:Int Field BlankPos:TPoint Field LastMove:TPoint Field LastTileMoved:Int = -1 Rem Moves the selected piece if possible 'returns >0 if successful, 0 if not EndRem Method MoveTile:Int(X:Int,Y:Int) 'no actual need to declare the parameter type as int since it is the default, 'but this helps prevent confusion Rem check that the specified tile can move, if it can, then move it and return true else return false EndRem Select CanTileMove(X,Y) Case 1 LastTileMoved = Board[X][Y] Board[X][Y-1] = Board[X][Y] Board[X][Y] = 0 BlankPos.X = x BlankPos.Y = y ?debug ' Print "BP:"+BlankPos.X + ", "+BlankPos.Y ? Return 1 Case 2 LastTileMoved = Board[X][Y] Board[X][Y+1] = Board[X][Y] Board[X][Y] = 0 BlankPos.X = x BlankPos.Y = y ?debug ' Print "BP:"+BlankPos.X + ", "+BlankPos.Y ? Return 2 Case 3 LastTileMoved = Board[X][Y] Board[X-1][Y] = Board[X][Y] Board[X][Y] = 0 BlankPos.X = x BlankPos.Y = y ?debug ' Print "BP:"+BlankPos.X + ", "+BlankPos.Y ? Return 3 Case 4 LastTileMoved = Board[X][Y] Board[X+1][Y] = Board[X][Y] Board[X][Y] = 0 BlankPos.X = x BlankPos.Y = y ?debug ' Print "BP:"+BlankPos.X + ", "+BlankPos.Y ? Return 4 Default Return 0 End Select End Method Rem Returns 0 if the tile can't move, nonzero if it can the nonzero value represents the direction that the tile can move 1 up 2 down 3 left 4 right An individual tile should only be able to at most move in one direction EndRem Method CanTileMove:Int(X:Int,Y:Int) 'check up If Y > 0 Then'if not at top edge If Board[x][y-1] = 0 Then Return 1 EndIf 'check down If Y < Len(Board)-1 Then ' if not at the bottom edge If Board[x][y+1] = 0 Then Return 2 EndIf 'check left If X > 0 Then 'if not at the left edge If Board[x-1][y] = 0 Then Return 3 EndIf 'check right If X < Len(Board)-1 Then 'if not at the right edge If Board[x+1][y] = 0 Then Return 4 EndIf Return 0 End Method Rem Use Shuffle to randomize the board (note that it will mix it up by moving the tiles around so that the solution is valid) the difficulty will be used to determine how many times the pieces are moved End Rem Method Shuffle(Diff: Int, Speed:Int = 500, SlowMo:Int=False)'if SlowMo is true then display each move Local CurrentMove:TPoint Local m:Int CurrentMove = New TPoint If Diff < 1 Then Diff= 1 'can't have a value less than 1 Difficulty = Diff For m = 0 To Difficulty*5 'CurrentMove = GetMove() 'make sure we are not doing the last move CurrentMove = GetMove() 'If CurrentMove.X = -1 Or CurrentMove.Y = -1 Then DebugStop LastMove.X = CurrentMove.X LastMove.Y = CurrentMove.Y MoveTile(CurrentMove.X, CurrentMove.Y) Target:+1 If SlowMo Then Draw() Flip Cls Delay Speed EndIf Next End Method Method GetMove:TPoint() Rem Each element represents a direction 0=up 1=down 2=left 3=right If it contains a TPoint value with values above zero then the tile in that direction can move EndRem Local CanMove:Int[4] Local Result:TPoint = New TPoint If BlankPos.Y > 0 Then If (Board[BlankPos.X][BlankPos.Y - 1]) And (Board[BlankPos.X][BlankPos.Y - 1] <> LastTileMoved) Then CanMove[0] = 1 EndIf EndIf If BlankPos.Y < Height-1 Then If (Board[BlankPos.X][BlankPos.Y + 1]) And (Board[BlankPos.X][BlankPos.Y + 1] <> LastTileMoved) Then CanMove[1] = 1 EndIf EndIf If BlankPos.X > 0 Then If (Board[BlankPos.X - 1][BlankPos.Y]) And (Board[BlankPos.X - 1][BlankPos.Y] <> LastTileMoved) Then CanMove[2] = 1 EndIf EndIf If BlankPos.X < Width-1 Then If (Board[BlankPos.X + 1][BlankPos.Y]) And (Board[BlankPos.X + 1][BlankPos.Y] <> LastTileMoved) Then CanMove[3] = 1 EndIf EndIf Local rn = Rand(0,3) Local GotMove = False While Not GotMove rn = Rand(0,3) If CanMove[rn] = 1 Then GotMove = True Wend Select rn Case 0 Result.X = BlankPos.X Result.Y = BlankPos.Y-1 Case 1 Result.X = BlankPos.X Result.Y = BlankPos.Y+1 Case 2 Result.X = BlankPos.X-1 Result.Y = BlankPos.Y Case 3 Result.X = BlankPos.X+1 Result.Y = BlankPos.Y End Select Return Result End Method Rem Call reset() to put the tiles back in the starting position EndRem Method Reset() Local X:Int,Y:Int Local Num:Int = 0 For X = 0 To Width-1 For Y = 0 To Height - 1 num :+ 1 'add 1 to num Board[Y][X] = num Next Next 'remove the last piece from the board Board[Width-1][Height-1] = 0 MoveCount = 0 Target = 0 BlankPos.X = 4 BlankPos.Y = 4 End Method Rem Draw the tiles to the screen EndRem Method Draw() Local X:Int,Y:Int For X = 0 To Width - 1 For Y = 0 To Height - 1 If Board[X][Y] > 0 Then 'loop through each element in the board array and draw the appropriate image DrawImage(img, X*TileWidth, Y*TileHeight, Board[X][Y]-1)'because we are using an animated image, we can use the number stored in each element as a frame number EndIf Next Next DrawText("Moves:" + MoveCount + " Target: " + Target, 0,400) End Method Method CheckInput() If MouseDown(1) Then Local mx:Int = MouseX() Local my:Int = MouseY() If mx < (Width * TileWidth) And mx > 0 Then If my < (Height * TileHeight) And my > 0 'if mouse is over tiles If MoveTile(mx / TileWidth, my / TileHeight) Then MoveCount:+1 EndIf EndIf EndIf End Method Method CheckWin:Int() 'if all the tiles are in the correct order, then we've won 'return 0 if false, 1 if true Local X:Int Local Y:Int Local count:Int If BlankPos.X < Width-1 Or BlankPos.Y < Height-1 Then Return 0 'if the blank position is not bottom right 'then we cannot possibly have won, so exit For X = 0 To Width - 1 For Y = 0 To Height - 1 Count :+ 1 If count < Width*Height Then If Board[Y][X] <> Count Then Return 0 EndIf Next Next Return 1 End Method Method CalcScore:Int() Return (((Difficulty * Target) - MoveCount)*10) + (Difficulty * Difficulty ) End Method Function Create:TSpuzzleBoard(Width:Int, Height:Int, ImageFile:String) Local brd:TSpuzzleBoard = New TSpuzzleBoard Local tempImg:TImage = LoadImage(ImageFile, DYNAMICIMAGE) Local _W:Int = ImageWidth(tempImg) Local _H:Int = ImageHeight(tempImg) Local Num:Int = 0 Local X:Int Local Y:Int brd.TileWidth = _W/Width brd.TileHeight = _H / Height brd.Width = Width brd.Height = Height brd.Board = brd.Board[..Height] For Y = 0 To Len(brd.Board)-1 brd.Board[Y] = brd.Board[Y][..Width] Next brd.LastMove = New TPoint brd.LastMove.X = -1 brd.LastMove.Y = -1 brd.LastTileMoved = -1 brd.BlankPos = New TPoint brd.Reset() 'reset the board pieces brd.img = LoadAnimImage(ImageFile, brd.TileWidth, brd.TileHeight, 0, Width*Height) tempImg = Null FlushMem Return brd End Function End Type Global GameEnded = False Global GameWon = False Global Level1:TSpuzzleBoard = TSpuzzleBoard.Create(5,5,"images/numbers.png") 'SET THE DIFFICULTY HERE (First parameter) Level1.Shuffle(4,100,True) 'MAIN LOOP While Not GameEnded If Not GameWon Then Level1.CheckInput() 'Check for user input If Level1.CheckWin() Then 'check to see if we've won yet GameWon = True EndIf Else DrawText("You have won!",0,420) DrawText("Score:"+Level1.CalcScore(),0,440) Delay 500 Level1.Board[Level1.Height-1][Level1.Width-1] = Level1.Width * Level1.Height EndIf Level1.Draw() 'tell our instance of the board to draw itself using the draw method 'use escape to end the game for now If KeyDown(KEY_ESCAPE) Then GameEnded = True Flip Cls FlushMem Wend 'END OF MAIN LOOP Level1 = Null FlushMem End
image used