Achievements

Previous topic - Next topic

MrTAToad

This is a little test program for an achievement system.  It could be regarded as inefficient, but when I post the code later, perhaps a better way could be found.

Anyway, see if you can find all the achievements :)  Using the cursor keys to move the block around

[attachment deleted by admin]

Kitty Hello

It looks nice. A bit too fast fadeout here.

backslider

Yes! Nice but really too fast :)
But it could be useful :)

MrTAToad

#3
QuoteA bit too fast fadeout here
Dont worry - you aren't missing much!

This is the code I am using :

Code (glbasic) Select
// --------------------------------- //
// Project: TestAchievements
// Start: Wednesday, June 23, 2010
// IDE Version: 8.006
TYPE tPlayerMovement
x%
y%
distX%
distY%
move%[]
achievementState%
moveXDir%
moveYDir%
ENDTYPE

TYPE tText
text$
x%
y%
alpha
ENDTYPE

PROTOTYPE achievements%:pm AS tPlayerMovement,text[] AS tText

TYPE tPlayer
text[] AS tText
pm AS tPlayerMovement
achievementPtr AS achievements
ENDTYPE

LOCAL player AS tPlayer
LOCAL loop AS tText

player.pm.x%=100
player.pm.y%=100
player.pm.distX%=0
player.pm.distY%=0
DIM player.pm.move%[32]
player.pm.achievementState%=0
player.pm.moveXDir%=0
player.pm.moveYDir%=0
player.achievementPtr=achievement1

LIMITFPS -1
SETFONT 0

LOADSOUND "Media/app-29.wav",0,4

WHILE TRUE
DRAWRECT player.pm.x%,player.pm.y%,16,16,RGB(255,0,0)

FOREACH loop IN player.text[]
ALPHAMODE loop.alpha
PRINT loop.text$,loop.x%,loop.y%
INC loop.alpha,0.005
IF loop.alpha>-0.01
DELETE loop
ENDIF
NEXT

SHOWSCREEN

INC player.pm.x%,player.pm.moveXDir%
INC player.pm.y%,player.pm.moveYDir%
IF player.achievementPtr
IF player.achievementPtr(player.pm,player.text[])
ENDIF
ENDIF
player.pm.moveXDir%=((-1*KEY(203))+(1*KEY(205)))
player.pm.moveYDir%=((-1*KEY(200))+(1*KEY(208)))
INC player.pm.distX%,ABS(player.pm.moveXDir%)
INC player.pm.distY%,ABS(player.pm.moveYDir%)
WEND

FUNCTION update%:pm AS tPlayerMovement,index%,text[] AS tText,extraText$
pm.move[index%]=TRUE
addAchievement(text[],extraText$)
PLAYSOUND(0,0.0,1.0)
RETURN TRUE
ENDFUNCTION

FUNCTION achievement1%:pm AS tPlayerMovement,text[] AS tText
IF pm.move[0]=FALSE AND pm.moveXDir%<0 THEN RETURN update(pm,0,text[],"Moving Left")
IF pm.move[1]=FALSE AND pm.moveXDir%>0 THEN RETURN update(pm,1,text[],"Moving Right")
IF pm.move[2]=FALSE AND pm.moveYDir%<0 THEN RETURN update(pm,2,text[],"Moving Up")
IF pm.move[3]=FALSE AND pm.moveYDir%>0 THEN RETURN update(pm,3,text[],"Moving Down")
IF pm.move[4]=FALSE AND pm.distX%>=10 THEN RETURN update(pm,4,text[],"10 horizontal moves")
IF pm.move[5]=FALSE AND pm.distX%>=100 THEN RETURN update(pm,5,text[],"100 horizontal moves")
IF pm.move[6]=FALSE AND pm.distX%>=1000 THEN RETURN update(pm,6,text[],"1000 horizontal moves")
IF pm.move[7]=FALSE AND pm.distX%>=10000 THEN RETURN update(pm,7,text[],"10000 horizontal moves")
IF pm.move[8]=FALSE AND pm.distX%>=100000 THEN RETURN update(pm,8,text[],"100000 horizontal moves")
IF pm.move[9]=FALSE AND pm.distX%>=1000000 THEN RETURN update(pm,9,text[],"100000 horizontal moves")
IF pm.move[10]=FALSE AND pm.distY%>=10 THEN RETURN update(pm,10,text[],"10 vertical moves")
IF pm.move[11]=FALSE AND pm.distY%>=100 THEN RETURN update(pm,11,text[],"100 vertical moves")
IF pm.move[12]=FALSE AND pm.distY%>=1000 THEN RETURN update(pm,12,text[],"1000 vertical moves")
IF pm.move[13]=FALSE AND pm.distY%>=10000 THEN RETURN update(pm,13,text[],"10000 vertical moves")
IF pm.move[14]=FALSE AND pm.distY%>=100000 THEN RETURN update(pm,14,text[],"100000 vertical moves")
IF pm.move[15]=FALSE AND pm.distY%>=1000000 THEN RETURN update(pm,15,text[],"100000 vertical moves")
IF pm.move[16]=FALSE AND pm.x%<=0 AND pm.y%<=0 THEN RETURN update(pm,16,text[],"Top Left corner!")
IF pm.move[17]=FALSE AND pm.x%>=640 AND pm.y%<=0 THEN RETURN update(pm,17,text[],"Top Right corner!")
IF pm.move[18]=FALSE AND pm.x%<=0 AND pm.y%>=480 THEN RETURN update(pm,18,text[],"Bottom Left corner!")
IF pm.move[19]=FALSE AND pm.x%>=640 AND pm.y%>=480 THEN RETURN update(pm,19,text[],"Bottom Right corner!")
IF pm.move[20]=FALSE AND pm.moveXDir%<0 AND pm.moveYDir%<0 THEN RETURN update(pm,20,text[],"Diagonal 1")
IF pm.move[21]=FALSE AND pm.moveXDir%>0 AND pm.moveYDir%>0 THEN RETURN update(pm,21,text[],"Diagonal 2")
IF pm.move[22]=FALSE AND pm.x%=640/2 AND pm.y%=480/2 THEN RETURN update(pm,21,text[],"Centre of screen!")
RETURN FALSE
ENDFUNCTION

FUNCTION addAchievement%:text[] AS tText,extra$
LOCAL t AS tText

DIM text[0]
t.text$="Congratulations!  Achievement awarded : "+extra$
t.x%=0
t.y%=0
t.alpha=-1.0
DIMPUSH text[],t
ENDFUNCTION


I had though of changing the function pointer for each achievement, but this would mean each achievement would be dependant on the previous one being completed, which isn't always the case.

The main thing is efficient code, with as little time as possible being taken to check for the achievements.

One thing I was thinking was having different pointers for each achievement that isn't dependant on any others (for example, corner, diagonal directional, and number of movements could each have their own pointer).

Once all achievement in a group has been completed, then the function pointer can be set to 0 so it wont need to be called, reducing the amount of checking needed to be done.

The other thing would be to use bitfields when an achievement has been completed