DrawImage/useing array data refrence bug/Error

BlitzMax Forums/BlitzMax Beginners Area/DrawImage/useing array data refrence bug/Error

RedWizzard(Posted 2016) [#1]
HI,

I am trying to make my games player objects (seprated from all objects)
In the game you can choose your playercolor / type (player 1 is red 2 bleu ectra)

I have made it so that the type of your player is a picture and your color is from a frame whitn that picture (picutres image is 25*25 frame 200)
So using type 1, color red is Image_1,Frame 1
Using type 1,color bleu is Image_1,frame 2 ectra

I setup a Playergrid[x,y] and a PlayersSdata[9],10 array
i have my drawplayer function wich draws the player
DrawPlayer(Player,X,Y,Playertype)

This all works fine until i use my updateplayer stuff function
The main game loop starts and loops troug varoiuse functions

Here is the strange thing. when i hardcode the DrawPlayer and PlayerSdata
into the main game loop it works fine.
showing player 1 to 8 each in there own outfit (knight wizzard ectra)

If i use the same style of code in my UpdateplayerStuff function
it will work but inccorect showing ALL types of player pictures
instead of only a knight or a wizzard.

I have added '**NOTE in my codes to explian my problem

The Main game loop showing both examples
[code]
'****************************************Time Picture clock


SetScale( 2,2 )

MapupdateLayer
'**NOTE The UpdatePlayerstuff shown in ohter code exmaples
'**NOTE does not work correctly

UpdatePlayerStuff KeyLR,KeyUD

UpdateObjectselectB SliderValue(slider)
BuildThis ItemC,KeyLR,KeyUD,MapLayer
UpdateItemVieuw ItemC,Mxz,MYz
MakeWall "C:\GameBuild\WizzardGame\DataFiles\SteelWall.PNG",2
DoInfo
SetLayer
If ButtonState (DataChekbut)=True Then ReportLayerinfo KeyLR,KeyUD
'**NOTE the hard coded Drawplayer wich works fine
DrawPlayer 1,2*50,2*50,PlayerSdata[1,1]
DrawPlayer 2,3*50,2*50,PlayerSdata[2,2]
DrawPlayer 3,4*50,2*50,PlayerSdata[3,3]
DrawPlayer 4,5*50,2*50,PlayerSdata[4,4]

DrawImage StBox,MXz,MYz
DrawText "WizzGameEngine 0.5",75,10

GUI_MouseGrid()

Flip 0
[/Code]

[Code]
Function DrawPlayer(Player:Int,X:Int,Y:Int,PlayerType:Int)

Local Picture:TImage=PImages[PlayerType]

If Player=1 Then DrawImage Picture,X,Y,0 'red
If Player=2 Then DrawImage Picture,X,Y,1 'blue
If Player=3 Then DrawImage Picture,X,Y,2 'green
If Player=4 Then DrawImage Picture,X,Y,3 'yellow
If Player=5 Then DrawImage Picture,X,Y,4 'Purple
If Player=6 Then DrawImage Picture,X,Y,5 'orange
If Player=7 Then DrawImage Picture,X,Y,6 'brown
If Player=8 Then DrawImage Picture,X,Y,7 'teal

End Function


Global PlayerGrid[GridMax_X,GridMax_Y]

'*****setup test data for players

'**NOTE setting up testplayers (1~8) at Grid X/Y
Playergrid[1,2]=1
Playergrid[1,3]=2
Playergrid[2,4]=3
Playergrid[3,5]=4
Playergrid[4,6]=5
Playergrid[1,7]=6
Playergrid[1,8]=7
Playergrid[1,9]=8

PlayerSdata[1,1]=1 '**NOTE this is the player type 1=Knight 2wizzard 3 monk
PlayerSdata[2,1]=2
PlayerSdata[3,1]=3
PlayerSdata[4,1]=3
PlayerSdata[5,1]=3
PlayerSdata[6,1]=2
PlayerSdata[7,1]=1
PlayerSdata[8,1]=3

Function UpdatePlayerStuff(KeyLR:Int,KeyUD:Int)
Local x;Local y;Local z;Local p
Local scroll_LR=KeyLR
Local scroll_UD=KeyUD
'Ft=Ft+Rnd(12)
For X = 1 To 25 'changed from 25
For Y = 1 To 12 'from 12
For P = 1 To 8
Print "data" + Playersdata[p,1]
DrawPlayer PlayerGrid[X+scroll_LR,Y+scroll_UD],X*50,Y*50,PlayerSdata[p,1]
Next
Next
Next

End Function


[/Code]

So i am a bit lost about how to slove it.
ash you can see I even test printed the outcome of the PlayerSdata[p,1]
doing print "data" + Playersdata[p,1]
and in the console it did show the correct number and it still
refused to show the correct picture

Is there any limitatoin of using arrays whitin functions i do not know of?
and how can i fix this?

Example picture of problem



Midimaster(Posted 2016) [#2]
your code looks a little bit chaotic...

here is a first solution without any great changes:
Function DrawPlayer(Player:Int,X:Int,Y:Int,PlayerType:Int)
	Local Picture:TImage=PImages[PlayerType]
	If Player=1 Then DrawImage Picture,X,Y,0 'red
	If Player=2 Then DrawImage Picture,X,Y,1 'blue
	If Player=3 Then DrawImage Picture,X,Y,2 'green
	If Player=4 Then DrawImage Picture,X,Y,3 'yellow
	If Player=5 Then DrawImage Picture,X,Y,4 'Purple
	If Player=6 Then DrawImage Picture,X,Y,5 'orange
	If Player=7 Then DrawImage Picture,X,Y,6 'brown
	If Player=8 Then DrawImage Picture,X,Y,7 'teal
End Function


Function UpdatePlayerStuff(KeyLR:Int,KeyUD:Int)
	Local x;Local y;Local z;Local p
	Local scroll_LR=KeyLR
	Local scroll_UD=KeyUD
	For X = 1 To 25 'changed from 25
		For Y = 1 To 12 'from 12
			Local Who% = PlayerGrid[X+scroll_LR,Y+scroll_UD]
			DrawPlayer Who, X*50, Y*50, PlayerSdata[Who,1]
		Next
	Next
End Function

Your third FOR/NEXT-loop is not necessary. The information who is on a certain grid position is in PlayerGrid[X+scroll_LR,Y+scroll_UD]. It is the number of a player. So you have to use this information twice to call the DrawPlayer function.

Additional I would add two changes in your code. The code shrinks to this:
Function DrawPlayer(Player:Int,X:Int,Y:Int,PlayerType:Int)
	DrawImage PImages[PlayerType], X, Y, Player-1
End Function


Function UpdatePlayerStuff(KeyLR:Int,KeyUD:Int)
	For Local X% = 1 To 25
		For Local Y% = 1 To 12
			Local Who% = PlayerGrid[X+KeyLR,Y+KeyUD]
                        If Who>0 AND Who<9
			     DrawPlayer Who, X*50, Y*50, PlayerSdata[Who,1]
                        Endif
		Next
	Next
End Function



Derron(Posted 2016) [#3]
Why are you drawing in the "update" routine?

Always separate logic from rendering - avoids issues (like assuming vsync works on all computers...)


bye
Ron


RedWizzard(Posted 2016) [#4]
Hi thank you Midimaster .
You have helped me good once again!

Still i have a few questions about the use of the blizmax language

I wonder wy my orignal script did not work?
As i see it i filled in the PlayersSdata array [p,1]
In wich p is the player and ,1 is the variable holder for the type of the player
So i tought i just loop trough that retrieving the correct player type At [Player,1]

as i have used arrays before i thougt it would retrive the right valeu given at
[1,1]=2 [2,1]=3 ectra

I Hope you can explian my error so i can learn from this situation.
I dont understand wy it is that when i hardcode the drawplayer function
It works like inteded retrieving the players type from the [p,1] data array

and when i do that in my function it displays all types of players at once.
I can see wy since it gets its data from the [p,1]=1 the functions itselfs does not change or add any values retrieved from the [p,1]

@Derron.
The Script shown here is for my editor
The main Update/Flip graphic loop is a functions it self wich is being called from my
Main drawing canvas. Its has a maxgui window controles and the grapics window in the middle. The function gets started by my EVENT_GADGETPAINT.
I am drawing becuase i should draw there. it is the main grapic/flip cls loop.

Wy do the variables X,Y and Who have a % next to them ??
Greetings Gijs


Ole JR(Posted 2016) [#5]

Wy do the variables X,Y and Who have a % next to them ??

Just another way to write :Int.

% = :Int
# = :Float
! = :Double
$ = :String


Midimaster(Posted 2016) [#6]
Hi RedWizzard,

...I'm an old school programmer. In former times we used shortcuts like "%" for ":INT" and I still do it. This defines the variables to a certain type.

It is a good style to always define your variables:
Superstrict
Const GRIDMAX_X:Int=25
Const GRIDMAX_Y:Int=12
Global PlayerGrid:Int[GRIDMAX_X,GRIDMAX_Y]
...


to your questions...

You say "why my orignal script did not work...". But it worked. Often the thing do not work like expected. So you have to find out what happened. Here the PRINT commands are your best friend. Add some more PRINTs to your code to watch, what happens.

If you keep the inner FOR/NEXT loop, too many call of the DRAWPLAYER function will happen. 25x12x8=2400 calls for only 300 fields.

f.e. the current field is 4/6, here stands Player 5. Then the inner FOR/NEXT calls 8 times the DRAWPLAYER:
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[1,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[2,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[3,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[4,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[5,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[6,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[7,1]
DrawPlayer 5 , 4*50, 6*50,PlayerSdata[8,1]

The DRAWPLAYER function receives 8 calls with player 5, but with the Sdata from all the others. This will cause painting 8 times:
Local Picture:TImage=PImages[1] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[2] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[3] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[3] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[3] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[2] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[1] 
If Player=5 Then DrawImage Picture,200, 300, 4 

Local Picture:TImage=PImages[3] 
If Player=5 Then DrawImage Picture,200, 300, 4 

so you will get a layer of 8 picture in one place

If you want to check ,what happens, the PRINT should look like this:
Function DrawPlayer(Player:Int,X:Int,Y:Int,PlayerType:Int)
     PRINT  "Player=" +Player+ "  X=" + X+ "    Y=" +Y+ "   TYPE= " +PlayerType
	Local Picture:TImage=PImages[PlayerType]
	If Player=1 Then DrawImage Picture,X,Y,0 'red
         .....


addiditonal you should have a PRINT command at the beginning of each loop
Function UpdatePlayerStuff(KeyLR:Int,KeyUD:Int)
        PRINT ""
        PRINT "******************************************"
        PRINT "new loop"
	For Local X% = 1 To 25
		For Local Y% = 1 To 12


To handle the big amount of PRINTs that now will happend you shoud reduce the number of field during the tests:
	For Local X% = 1 To 9
		For Local Y% = 1 To 9


and always a good adwise is to reduce the number of FLIPs during the test from normaly 60 downto 5 or 10. This causes a "slow motion" of your game:
FPS:TTimer=CreateTimer(10)
....
'main loop:
Repeat
     Cls
     Flip 0
     WaitTimer FPS
Until KeyHit(KEY_ESCAPE)



RedWizzard(Posted 2016) [#7]
Hi MidiMaster.

I havent programmed lately but to day i am at it again.
Thank you for the help and explanation of my bugged player loop.
I now c wy that did not work as intended
I still have al lot to learn.

That FPs timer seems handy il use it.

I am now at the point that i finished my editor.

all my objects are in an array. il have to use types.
dont know if i can use a main list for my players. and a sublist for the players objects.
Or if i should keep all object status in a new object array.

At this point i have two arrays that hold the creature objects.
One for the image and one for there statistics

I could use some advice on the best approach for
Creating gameobjects for all players. since the map is loaded the creauters are no
real objects, just images reprecented by an array. so i need to add that to the editor en main game

Thanks !


Midimaster(Posted 2016) [#8]
you are talking about "types". This is also a blitzmax command! And it would be the best way to handle players and their parameters and objects.

do you know something about types?

Type TPlayer
     Field X%, Y%, Character%, Token%[9], Image:TImage
End Type

This is a definition of a player who has x and y coordinates and a character (what you call the "type"), an images associated with the player. And this player can have upto 9 token (what you call objects) like weapons, etc..

Do you understand this?
Next step is to create a player of this type:
Peter:TPlayer=New Player
Peter.X=100
Peter.Y=200
Peter.Character=6 'brown
Peter.Token[1]= 1 'sword
Peter.Token[2]= 4 'additional life
Peter.Image=LoadImage("Picture.png")
...


Now you can work with this player like normal variables:
DrawImage Peter.Image, Peter.X, Peter.Y, Peter.Character


Start with this, this is a harmless usage of types. Later you will find out about LISTs and combinations of Types with arrays. This will multiplicate your skills.

Global PlayList:TList=New TList

local Peter:TPlayer = New TPlayer
Peter.X=....
....
PlayList.AddLast Peter


local Sam:TPlayer = New TPlayer
Sam.X=....
.....
PlayList.AddLast Sam



For local p:TPlayer = EachIn PlayList
     DrawImage DrawImage p.Image, p.X, p.Y, p.Character
Next



RedWizzard(Posted 2016) [#9]
Thanks Again Midimaster.

Yes i know that blitzmax hase types
I have not yet used them since i find them a bit hard and for now i have got my editor
to work whit only funtions/lists and arrays. i tried to make one type for my animation clock, i am making my game modable so i have multply objects/pictures that use animation,the scrpit counts the amount of frames in a picture and then the apropatie frame clock is used. i tried makeing the a frame clock type
so the user can add any amount of frames to an object i could not get it to work correctly so i discared the type and hardcoded 8 diffrant frametimers on fixed lenght

Your type example is helpfull i understand it.
As i see i will add a aditional list for the T.Player. so his creatures are in there.

The game i am trying to make is modable and turnbased.
Your a wizzard/Hero who has to defeat other wizzards.
You can roam around on the map and summon creatures for battle or use spells to
boost the creaters or your self, in example you can do a speed spell allowing you to
move a few squares more or trow flames at you enemy.
You summon creatures and attack you enemys creatures and his wizzard.

if you like i can add you to the credit list for all the help you have given
Greetings Gijs de Mik