Arkanoid style block color matching game

Monkey Forums/Monkey Code/Arkanoid style block color matching game

Pakz(Posted 2015) [#1]
More then 10 years ago my brother gave me a link of a game he was playing. I downloaded it and played it. I thought it was nice enough to remake and remade a basic version of it in blitz basic within the hour and showed it to my brother.

I now remade the game in Monkey. It took a little longer since I am still learning to use Monkey. I had problems with the blocks array. I am used to multi dimensional arrays so Monkey is a different biscuit.

I also have the code on my blog but it is good to have another backup of the code online,

The resolution the game is made for is 640*480 (monkey standard)

The pad moves left to right towards the mouse. There are key to grab a block and a key to release the block(s)

Here a screenshot:


Here a video :


Here the code:
' By Pakz (Rudy van Etten)

Import mojo

Global bca:Int=-1 ' blck color above the pad (padx+padwidth/2)
Const mapwidth:Int=8 'number of blocks wide
Const mapheight:Int=14 'number of blocks high minus 6
Const blockwidth:Int=64
Const blockheight:Int=22
Global blockactive:Int[mapwidth*mapheight] ' display block if value is 1 do not display if value is 0
Global blockcolor:Int[mapwidth*mapheight] 'block color - 4 block colors
Global padx:Int=320
Global pady:Int=480-22
Const padwidth:Int=64
Const padheight:Int=22
Global padblock:Int[6] 'Blocks ontop of the pad (colors)

Class MyGame Extends App
   
    Method OnCreate()
        SetUpdateRate(60)
        For Local i:Int=0 Until mapwidth*(mapheight-6)
        	blockactive[i] = 1
        	blockcolor[i] = Rnd(0,4)
		Next        
    End Method
	Method OnUpdate()
		If Rnd(20)<2 Then moveblocksdown()
		'Pad movement
		If padx+padwidth/2 < MouseX() Then padx+=5
		If padx+padwidth/2 > MouseX() Then padx-=5
		If padx>(mapwidth-1)*blockwidth Then padx=(mapwidth-1)*blockwidth
		If padx<0 Then padx = 0
		'Pad pickup
		bca = getblockcolorabove()
		If KeyHit(KEY_Q)
			If bca+1 = padblock[0] Or padblock[0] = 0
			If padblock[5] = 0
				For Local i=0 Until 6
					If padblock[i] = 0
						padblock[i] = bca+1
						removeblockabove()
						Exit
					End If
				Next
			End If
			End If
		End If
		If KeyHit(KEY_W)
			releaseblocks()
		End If
	End Method    
    Method OnRender()
        Cls
        SetColor 25,25,55
        DrawRect padx,0,padwidth,DeviceHeight
        'Draw pad
        SetColor 255,255,255
        DrawRect padx,pady,padwidth,padheight
		'blocks on the pad
		For Local i=0 Until 6
			If padblock[i] > 0
				Select padblock[i]
					Case 1 ; SetColor(255,0,0)
   		 			Case 2 ; SetColor(0,255,0)
   	 				Case 3 ; SetColor(0,0,255)
   	 				Case 4 ; SetColor(255,255,0)			
				End Select
				DrawRect padx,pady-(i*blockheight)-blockheight,blockwidth,blockheight
			End If
		Next

        'Draw blocks
        For Local i:Int=0 Until mapwidth*mapheight
	       	If blockactive[i] = 1
       			Select blockcolor[i]
       				Case 0 ; SetColor(255,0,0)
       				Case 1 ; SetColor(0,255,0)
       				Case 2 ; SetColor(0,0,255)
       				Case 3 ; SetColor(255,255,0)
      			End Select
       			DrawRect getx(i)*blockwidth,gety(i)*blockheight,blockwidth,blockheight
    	   	End If
        Next
        SetColor 255,255,255
        DrawText "Q to Grab",640-120,10
        DrawText "W to Return",640-120,30
    End Method
    
End

Function Main:Int()
    New MyGame()
End

Function getx:Int(i:Int)
	Return i Mod mapwidth 
End Function
Function gety:Int(i:Int)
	Return i / mapwidth
End Function
Function blockvalue:Int(x:Int,y:Int)
	Return y * mapwidth + x
End Function
Function maxpadblocks:Bool()
	Local cnt:Int=0
	For Local i=0 Until 6
		If padblock[i] > 0 Then cnt+=1
	Next
	If cnt=5 Then Return True
	Return False
End Function
Function getblockcolorabove:Int()
	Local px:Int = padx+padwidth/2
	Local py:Int = pady-padheight
	For Local y=py Until -20 Step -blockheight/2
		For Local i=0 Until mapwidth*mapheight
			If blockactive[i] = 1
			Local x1 = getx(i)*blockwidth
			Local y1 = gety(i)*blockheight
			If rectsoverlap(px,y,5,5,x1,y1,blockwidth,blockheight) = True Then
				Return blockcolor[i]
			End If
			End If
		Next
	Next
	Return -1
End Function
Function removeblockabove:Bool()
	Local px:Int = padx+padwidth/2
	Local py:Int = pady-padheight
	For Local y=py Until -20 Step -blockheight/2
		For Local i=0 Until mapwidth*mapheight
			If blockactive[i] = 1
			Local x1 = getx(i)*blockwidth
			Local y1 = gety(i)*blockheight
			If rectsoverlap(px,y,5,5,x1,y1,blockwidth,blockheight) = True Then
				blockactive[i] = 0
				Return True
			End If
			End If
		Next		
	Next
	Return False
End Function

Function padblockcount:Int()
	Local cnt:Int=0
	For Local i=0 Until 6
		If padblock[i] > 0 Then cnt+=1
	Next
	Return cnt
End Function

Function releaseblocks:Bool()
	If padblock[0] = 0 Then Return False
	Local px:Int = padx+padwidth/2
	Local py:Int = pady-padheight
	For Local y=py Until -20 Step -blockheight/2
		For Local i=0 Until mapwidth*mapheight
			If blockactive[i] = 1
			Local bc = blockcolor[i]
			Local x1 = getx(i)*blockwidth
			Local y1 = gety(i)*blockheight
			If rectsoverlap(px,y,5,5,x1,y1,blockwidth,blockheight) = True Then
				If gety(i) + padblockcount() >= mapheight-1 Then Return False
				If padblock[0]-1 = bc Then
					For Local ii=0 Until 6
						padblock[ii] = 0
						blockactive[i] = 0
					Next
					Return
				End If				
				For Local ii=0 Until 6
					If padblock[ii] > 0
						blockactive[i+(ii*mapwidth+(mapwidth))] = 1
						blockcolor[i+(ii*mapwidth+(mapwidth))] = padblock[ii]-1						
						padblock[ii] = 0
					End If
				Next
				Return
			End If
			End If
		Next		
	Next
End Function

Function rectsoverlap:Int(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)
    If x1 > (x2 + w2) Or (x1 + w1) < x2 Then Return False
    If y1 > (y2 + h2) Or (y1 + h1) < y2 Then Return False
    Return True
End

Function moveblocksdown:Bool()
	Local y:Int=mapheight-6
	Local erase:Bool = True
	For Local x=0 Until mapwidth
		If blockactive[blockvalue(x,y)] = 1 Then erase = False
	Next
	If erase = True
		For Local y1=mapheight-1 To 1 Step -1
		For Local x1=0 Until mapwidth
			Local i = blockvalue(x1,y1)
			blockactive[i] = blockactive[blockvalue(x1,y1-1)]
			blockcolor[i] = blockcolor[blockvalue(x1,y1-1)]
		Next
		Next
		For Local x1=0 Until mapwidth
			Local i = blockvalue(x1,0)
			blockactive[i] = 1
			blockcolor[i] = Rnd(0,4)
		Next
	End If
End Function



Snader(Posted 2015) [#2]
You have a lot of nice examples for beginner monkey users Rudy! Thumbs up!


Supertino(Posted 2015) [#3]
EDIT nvm I see you do this in your tutorials you posted.

if it helps you can emulate multi-dim arrays.


Global width:Int=13
Global height:Int=12
Global myArray:Int[][]

' // initialise the array
myArray = AllocateArray(width,height)

 ' // change a value
myArray[3][5] = 4
myArray[5][7] = 2

' // Draw all values in 20px blocks on screen
for local x:Int=0 until width-1
for local y:Int=0 until hight-1
   DrawText myArray[x][y],x*20,y*20
next
next

' // Initializer function 
Function AllocateArrayInt:Int[][]( i:Int, j:Int)
    Local arr:Int[][] = New Int[i][]
    For Local ind = 0 Until i
        arr[ind] = New Int[j]
    Next
    Return arr		
End




Steve Ancell(Posted 2015) [#4]
This is how I access one dimensional arrays with 2D coordinates. It's quick, dirty, and it will work fine for tilemaps, brick and ball, and falling block games etc...




Strict
Import mojo


Global _gColumnCount:Int
Global _gRowCount:Int
Global _gArray:Int[]


Function Main:Int()
	New C_App()
	Return 0
	
End




Class C_App extends App
	Method OnCreate:Int()
		_fArrayPopulate2D(10, 10)
		_fArrayEdit2D(4, 4, 123)
		Return 0
		
	End
	
	Method OnUpdate:Int()
		Return 0
		
	End
	
	Method OnRender:Int()
		Cls
		_fDrawArray2D()
		Return 0
		
	End
	
End




Function _fArrayPopulate2D:Void(columnCount:Int, rowCount:Int)
	Local lColumn:Int
	Local lRow:Int
	
	
	_gColumnCount = columnCount
	_gRowCount = rowCount
	
	For lRow = 0 to (rowCount - 1)
		For lColumn = 0 to (columnCount - 1)
			_gArray = _gArray.Resize(_gArray.Length() + 1)
			_gArray[lColumn + (columnCount * lRow)] = 0
			
		Next
		
	Next
	
End




Function _fArrayEdit2D:Void(column:Int, row:Int, value:Int)
	Local lArrayAddress:Int
	
	
	lArrayAddress = column + (_gColumnCount * row)
	
	_gArray = _gArray.Resize(_gArray.Length() + 1)
	_gArray[lArrayAddress] = value
	
End




Function _fDrawArray2D:Void()
	Local lArrayAddress:Int
	Local lColumn:Int
	Local lRow:Int
	
	
	For lRow = 0 to (_gRowCount - 1)
		For lColumn = 0 to (_gColumnCount - 1)
			lArrayAddress = lColumn + (_gColumnCount * lRow)
			DrawText(_gArray[lArrayAddress], lColumn * 35, lRow * 35)
			
		Next
		
	Next
	
End



Steve Ancell(Posted 2015) [#5]
I just viewed your video, I like the way you've managed to fuse Arkanoid and Klax into one game. Great stuff.


ElectricBoogaloo(Posted 2015) [#6]
There seems to be something missing.
It's all kind of slow and formulated, and there's no "risk" to the game.

If it were me, I'd throw in a ball, bouncing around, and make it deadly so that you had to avoid it. It'd make for a unique dodge-em-up!


Pakz(Posted 2015) [#7]
The original that I played was different. This part was the only thing I remembered. Maybe there were aliens and such in it to, I can't remember. I can not find the original anymore.

edit : I found a game like it. Space stacker it is called. There the blocks keep moving down every few seconds so you need to get rid of the blocks as fast as possible. I can not remember if this was the game I played then.