'Gimme Friction Baby' for the small screen

Miscellaneous Forums/Blitz Showcase/'Gimme Friction Baby' for the small screen

Today I was just thinking about trying to write a game for my phone.. in Java probably.

Anyway.. I was trying to think what to write and I remembered a browser game called 'Gimme Friction Baby' where the controls where just 1 button.
So.. tonight I thought I'd try to write a prototype in blitzMax.. and here is my results.

The code isnt pretty.. it was after all written in about 5 hours and written on the fly.

its runs in a 240x320 window.. to match my phone.

Just thought I'd share.



and here is a windows exe GimmeFrictionBabyMobile.zip

Added : Spent another hour or so adding improvements. Spheres now contain a number indicating how many hits remaining before it disapears.
firing sphere size increased ( maily so the numbers would fit inside it ).
SuperStrict
' Program     : Gimme Friction Baby Mobile ( prototype )
' Author      : QuietBloke
' Date        : 21st March 2008
' Description : This is a clone of the winner of a "Casual Gampley Design Competition"
' Please visit www.jayisgames.com and check out the competitions to see the original games.
' "Gimme Friction Baby" was written by Wouter Visser of The Netherlands
' The idea for this prototype is to see if I could recreate the game for the small screen
' so it can fit onto a mobile phone.

Type TGameTemplate
	Field quit:Int
	
	Method Start() Abstract
	Method Update() Abstract
	Method Draw() Abstract
	Method Pause() Abstract
	Method Finish() Abstract

	Method DoQuit()
		quit = True
	End Method
End Type

Type TVector
	Field x:Float
	Field y:Float
	
	Method Rotate(angle:Float)
		Local tempX:Int
		Local tempY:Int
		tempX = x
		tempY = y
		x = Cos(angle) * tempX - Sin(angle) * tempY
		y = Sin(angle) * tempX + Cos(angle) * tempY
	End Method
	
	Method GetMagnitude:Float()
		Return Sqr(x*x + y*y )
	End Method
	
	Method SetMagnitude(newMagnitude:Float)
		Normalise()
		x :* newMagnitude
		y :* newMagnitude
	End Method
	
	Method Normalise()
		Local magnitude:Float
		magnitude = GetMagnitude()
		x :/ magnitude
		y :/ magnitude
	End Method
	
	Method DotProduct:Float(v:TVector)
		Return x*v.x + y*v.y
	End Method
	
	Method ScalarMultiply(scalar:Float)
		x :* scalar
		y :* scalar
	End Method
End Type

Type TPolyRects
	Field rects:TList
	Field pos:TVector
	Field angle:Float
	Field scale:Float
		
	Method New()
		rects = CreateList()
		pos = New TVector
		scale = 1
	End Method
	
	Method AddRect(pointArray:Float[])
		Local rect:TPolyRect = New TPolyRect
		
		rect.pos = pos
		rect.pointArray = pointArray
		rect.scale = scale
		rect.angle = angle
		
		ListAddLast(rects,rect)
	End Method
	
	Method Update()
		Local rect:TPolyRect
		
		For rect = EachIn rects
			rect.angle = angle
			rect.scale = scale
			rect.pos = pos
		Next
	End Method
	
	Method Draw()
		Local rect:TPolyRect
		
		For rect = EachIn rects
			rect.Draw()
		Next
	End Method
End Type

Type TPolyRect
	Field pos:TVector
	Field angle:Float
	Field pointArray:Float[8]
	Field scale:Float
	
	Method New()
		pos = New TVector
		scale = 1
	End Method
	
	Method Update()
	End Method
	
	Method Draw()
		SetOrigin pos.x,pos.y
		SetRotation angle
		SetScale scale,scale
		DrawPoly(pointArray)
		SetOrigin 0,0
		SetRotation 0
		SetScale 1,1
	End Method
End Type

Type TPoly3 Extends TPolyRects
	Method New()
		Local pointArray:Float[8]
		
		pointArray[0] = -5
		pointArray[1] = -5

		pointArray[2] = 5
		pointArray[3] = -5

		pointArray[4] = 5
		pointArray[5] = -3

		pointArray[6] = -5
		pointArray[7] = -3
		
		Addrect(pointArray)

		pointArray = New Float[8]
		
		pointArray[0] = 3
		pointArray[1] = -5

		pointArray[2] = 5
		pointArray[3] = -5

		pointArray[4] = 5
		pointArray[5] = 5

		pointArray[6] = 3
		pointArray[7] = 5

		Addrect(pointArray)

		pointArray = New Float[8]

		pointArray[0] = -3
		pointArray[1] = -1

		pointArray[2] = 5
		pointArray[3] = -1

		pointArray[4] = 5
		pointArray[5] = 1

		pointArray[6] = -3
		pointArray[7] = 1
		
		Addrect(pointArray)

		pointArray = New Float[8]
		pointArray[0] = -5
		pointArray[1] = 3

		pointArray[2] = 5
		pointArray[3] = 3

		pointArray[4] = 5
		pointArray[5] = 5

		pointArray[6] = -5
		pointArray[7] = 5
		
		Addrect(pointArray)

	End Method
End Type

Type TPoly2 Extends TPolyRects
	Method New()
		Local pointArray:Float[8]
		
		pointArray[0] = -5
		pointArray[1] = -5

		pointArray[2] = 5
		pointArray[3] = -5

		pointArray[4] = 5
		pointArray[5] = -3

		pointArray[6] = -5
		pointArray[7] = -3
		
		Addrect(pointArray)

		pointArray = New Float[8]
		
		pointArray[0] = 3
		pointArray[1] = -5

		pointArray[2] = 5
		pointArray[3] = -5

		pointArray[4] = 5
		pointArray[5] = 1

		pointArray[6] = 3
		pointArray[7] = 1

		Addrect(pointArray)

		pointArray = New Float[8]
		
		pointArray[0] = -5
		pointArray[1] = -1

		pointArray[2] = 5
		pointArray[3] = -1

		pointArray[4] = 5
		pointArray[5] = 1

		pointArray[6] = -5
		pointArray[7] = 1

		Addrect(pointArray)
		
		pointArray = New Float[8]
		
		pointArray[0] = -5
		pointArray[1] = -1

		pointArray[2] = -3
		pointArray[3] = -1

		pointArray[4] = -3
		pointArray[5] = 5

		pointArray[6] = -5
		pointArray[7] = 5

		Addrect(pointArray)

		pointArray = New Float[8]

		pointArray[0] = -5
		pointArray[1] = 3

		pointArray[2] = 5
		pointArray[3] = 3

		pointArray[4] = 5
		pointArray[5] = 5

		pointArray[6] = -5
		pointArray[7] = 5
		
		Addrect(pointArray)


	End Method
End Type

Type TPoly1 Extends TPolyRects
	Method New()
		Local pointArray:Float[8]
		
		pointArray[0] = -1
		pointArray[1] = -5

		pointArray[2] = 1
		pointArray[3] = -5

		pointArray[4] = 1
		pointArray[5] = 5

		pointArray[6] = -1
		pointArray[7] = 5
		
		Addrect(pointArray)
	End Method
End Type

Type TTurret Extends TPolyRects
	Field direction:Float

	Method New()
		Local pointArray:Float[8]
		pos.x = 120
		pos.y = 320-40

		pointarray[0] = 0
		pointarray[1] = -8

		pointarray[2] = 35
		pointarray[3] = -8

		pointarray[4] = 35
		pointarray[5] = 8

		pointarray[6] = 0
		pointarray[7] = 8
		
		AddRect(pointArray)

		pos.x = 120
		pos.y = 320-40		
		
		angle = 340
		
		direction = -1
		Super.Update()
	End Method

	Method Update()
		angle :+ direction
		If angle >= 340 Then
			angle = 340
			direction :* -1
		End If
		If angle < 200 Then
			angle = 200
			direction :* -1
		End If
		
		Super.Update()
	End Method
End Type

Type TSphere
	Global spheres:TList = CreateList()
	Global outOfBounds:Int
	Global score:Int

	Field lifePoly:TPolyRects
		
	Field pos:TVector
	Field velocity:TVector
	Field radius:Int
	Field expanding:Int
	Field life:Int
	Field colour:Int
	
	Method New()
		pos = New TVector
		velocity = New TVector
		ListAddLast(spheres,Self)
		radius = 8
		life = 3
		colour = 255
	End Method
	
	Method SetVelocity(magnitude:Float,angle:Float)
		velocity.x = magnitude
		velocity.y = 0
		velocity.Rotate(angle)
	End Method

	Method Hit()
		life :- 1
		If life > 0 Then
			Local angle:Float = lifePoly.angle
			Select life
				Case 1
					lifePoly = New TPoly1
				Case 2
					lifePoly = New TPoly2
			End Select
			lifePoly.pos = pos		
			lifePoly.scale = radius/8.0
			lifePoly.angle = angle
			lifePoly.Update()
		Else
			score :+ 1
		End If
		
	End Method
	
	Function Reset()
		score = 0
		spheres = CreateList()
		outOfBounds = False
	End Function
	
	Method IsStopped:Int()
		If velocity.GetMagnitude() = 0 And expanding = False
			Return True
		Else
			Return False
		End If
	End Method
	
	Method Draw()
		SetColor colour,colour,colour
		DrawOval pos.x-radius, pos.y-radius, radius*2, radius*2
		
		If lifePoly <> Null Then
			SetColor 0,0,0
			lifePoly.Draw()
			SetColor 255,255,255
		End If
	End Method
	
	Method Update()
		' if we are expanding then increase the size if we can
		If expanding Then
			Local hit:Int = False
			'will expansion collide with a wall
			If pos.x -radius -1 < 0 Then
				hit = True
			End If
			If pos.x + radius + 1 > 239 Then
				hit = True
			End If
			If pos.y - radius - 1 < 0 Then
				hit = True
			End If
			If pos.y + radius > 239 Then
				hit = True
			End If
			' see if expanding will collide with another sphere
			Local sphere:TSphere
			
			For sphere = EachIn spheres
				If sphere <> Self And sphere.life > 0 Then
					' find distance from centers of spheres
					Local distance:Float = Sqr((pos.x-sphere.pos.x)*(pos.x-sphere.pos.x) + (pos.y-sphere.pos.y)*(pos.y-sphere.pos.y))
					Local mindistance:Float = radius + sphere.radius
					If distance <= minDistance Then
						hit = True
					End If
				End If
			Next			
			If hit Then
				expanding = False
			Else
				radius :+ 1
				lifePoly.scale = radius/8.0
				lifePoly.Update()
			End If
		Else
			' if we are moving then we must do collision detection
			If velocity.GetMagnitude() <> 0 Then
				' see if we stop the ball
				If velocity.GetMagnitude() <= .04 Then
					SetVelocity(0,0)
					pos.x = Int(pos.x)
					pos.y = Int(pos.y)
					' Expand the ball until it cannot expand anymore
					expanding = True
					lifePoly = New TPoly3
					lifePoly.pos = pos	
					lifepoly.angle = Rand(-35,35)
				Else
					' see if we need to bounce off a wall
					If pos.x - radius  < 0 Then
						velocity.x :* -1
						pos.x = radius 
					End If
					If pos.x + radius > 239 Then
						velocity.x :* -1
						pos.x = 239 - radius
					End If
					If pos.y - radius < 0 Then
						velocity.y :* -1
						pos.y = radius
					End If
					' see if we need to bounce off another sphere
					Local sphere:TSphere
					For sphere = EachIn spheres
						If sphere <> Self And sphere.life > 0 Then
							' find distance from centers of spheres
							Local distance:Float = Sqr((pos.x+-sphere.pos.x)*(pos.x-sphere.pos.x) + (pos.y-sphere.pos.y)*(pos.y-sphere.pos.y))
							Local mindistance:Float = radius + sphere.radius
							If distance <= minDistance Then
								' first shift our sphere back until we are not overlapping the other sphere
								Local m:TVector = New TVector
								m.x = sphere.pos.x - pos.x
								m.y = sphere.pos.y - pos.y
								m.Normalise()
								m.ScalarMultiply(minDistance-distance)
								pos.x :- m.x
								pos.y :- m.y
								
								' find the collision normal 
								Local collisionNormal:TVector = New TVector
								collisionNormal.x = pos.x - sphere.pos.x
								collisionNormal.y = pos.y - sphere.pos.y
								collisionNormal.Normalise()
								
								Local j:Float
								j = (-2 * (velocity.DotProduct(collisionNormal)) / collisionNormal.DotProduct(collisionNormal))
								
								collisionNormal.x :* j
								collisionNormal.y :* j
								velocity.x :+ collisionNormal.x
								velocity.y :+ collisionNormal.y 
								
								sphere.Hit()
							End If 
						End If
					Next

					pos.x :+ velocity.x
					pos.y :+ velocity.y
			
					If velocity.y >= 0 And pos.y + radius > 239 Then
						outOfBounds = True
					End If
					velocity.SetMagnitude(velocity.GetMagnitude()-.04)
				End If
			End If
		End If
	End Method
	
	Function CreateSphere:TSphere(posX:Float, posY:Float, speed:Float, angle:Float)
		Local sphere:TSphere
		
		sphere = New TSphere
		sphere.pos.x = posX
		sphere.pos.y = posY
		sphere.SetVelocity(speed,angle)
		
		Return sphere
	End Function
	
	Function UpdateAll()
		Local sphere:TSphere
		
		For sphere = EachIn spheres
			If sphere.life < 1 And sphere.colour <= 0 Then
				ListRemove(spheres,sphere)
			Else
				If sphere.life < 1 Then
					sphere.colour :- 16
				Else
					sphere.Update()
				End If
			End If
		Next
	End Function
	
	Function DrawAll()
		Local sphere:TSphere
		
		For sphere = EachIn spheres
			sphere.Draw()
		Next
	End Function
End Type

Type TGame Extends TGameTemplate
	Field turret:TTurret
	Field movingSphere:TSphere
	Field gameStage:Int
	Field colour:Int
	Field colourShift:Int
	
	Method New()
		colourShift = -5
		colour = 255
		
	End Method
	
	Method Start()
		Graphics 240,320,0,30
		
		'create the turret
		turret = New TTurret		
	End Method
	
	Method Update()
		If KeyHit(KEY_Escape) Then
			DoQuit()
		End If
		
		If gameStage = 1 Then
			If KeyHit(KEY_Space) Then
				If movingSphere = Null Then
					FireSphere()
				Else
					If movingSphere.IsStopped() Then
						FireSphere()
					End If
				End If
			End If
			
			turret.Update()
			TSphere.UpdateAll()
			
			If TSphere.outOfBounds Then
				gameStage = 0
				colour = 255
				colourShift = -5
			End If
		Else
			If gameStage = 0 Then
				colour :+ colourShift
				If colour <= 5 Or colour >= 255 Then
					colourShift :* -1
				End If
				If KeyHit(Key_SPACE) Then
					TSphere.Reset()
					movingSphere = Null
					turret = New TTurret
					gameStage = 1
				End If
			End If
		End If
	End Method

	Method FireSphere()
		Local startOffset:TVector
		startOffset = New TVector
		startOffset.x = 30
		startOffset.y = 0
		startOffset.Rotate(turret.angle)

		movingSphere = TSphere.CreateSphere(120+startOffset.x,320-40+startOffset.y,5,turret.angle)
	End Method
	
	Method Draw()
		' draw a dotted line marking the bottom of the play area
		Local x:Int
		
		SetColor 255,255,255
		For x = 0 To 240 Step 10
			DrawLine x,240,x+5,240
		Next
		
		'draw the ground
		DrawRect 0,320-20,240,320
		
		' draw the turret base
		DrawRect 120-20,320-40,40,40
		DrawOval 120-20,320-60,40,40

		' draw the turret
		turret.Draw()

		TSphere.DrawAll()
		
		SetColor 0,0,0
		DrawText "Score : " + TSphere.score,80,320-18
		
		SetColor colour,colour,colour
		If gameStage = 0 Then
			DrawText "Press 'SPACE'",70,100
			DrawText "to begin",80,120
		End If
	End Method
	
	Method Pause()
	End Method
	
	Method Finish()
	End Method
End Type

Global game:TGame = New TGame

Global finished:Int

game.Start()
While Not game.quit
	game.Update()
	Cls
	game.Draw()
	Flip
Wend

game.Finish()

End


Forgot to mention : the only key you need to play is the space key. Press Escape to quit the game.

The aim of the game is a little hard to explain.
You fire a ball. When it stops moving it will expand until it reaches a wall or another ball.
When you hit a stationary ball 3 times it will be removed from the play area and you will score 1 point.
The game ends when a ball falls down below the dotted line.

no replys.. so either its in the wrong forum ( I really couldnt decide where to put it ) or its just not worth a comment.

Maybe I need to think of another game that might work well for a phone.

In the meantime I'm off to learn how to write a Midlet. Its a shame there isnt a Mobile version of BlitzMax.

Interesting idea - simple but I haven't seen a game like this before... Nice work ;-)

People love screenshots. Try that to pique interest, and upload an exe for non-BMax users. that'll get more comments :-)

thanx Grey.. good point.. tis done..
I was just wondering if people thought it would make a good game for a phone.. plus test it to see if there were any bugs.
I have tried to make the game look as close to the original as possible.

looks fun, curious though, Bmax compiles on a cell phone? how does that work exactly if you don't mind explaining..

I wish BMax could compile onto a cell phone. What i am going to have to do is port the code to java now. It was just far quicker to write and test the game logic in BMax.

Interesting concept -- I like it -- good job. I think given a bit more time and some bells and whistles you could have a decent java phone game.

thanx.. Im now trying to re-learn java and working through the documentation to figure out how to write a midlet and work through the API's. One thing Ive just discovered is the mobile java does not have floats so I may have to revisit the code and convert it to just use int's... that will be fun !
Maybe while I do that I'll add some 'bells and whistles'.. if only to give my brain a break.