How put sprite position in pixels into array

Started by Aurel [banned], June 19, 2022, 19:43:46

Previous topic - Next topic

Aurel [banned]

hello
I hope that my question is not stupid
if is tell me  ;D

ok
i am trying to put sprite position in pixels  into one dimensional array
which looks like set of tiles ...i am really rookie for games so i want to know
is that even possible .
here is how my window looks:
(Y)

Aurel [banned]

I get it how to calculate X pos of cell as you may see from image
but is that proper way to track sprite ?
(Y)

guest8544



Midimaster

Of course it is possible to also calculate positions in such an one-dimensional array.

You have 24 elements in each row. So walking to the right is +1 and walking to the left is -1. walking up is -24 and walking down is +24.

To calculate the real screen cell you have to divide by 24. The INTEGER result brings you the row, the MODULO brings you the column. Because you start not with cell "0" but with cell "1" you have to substract 1 before calculating. Afterward you need to add "1" again to get back into "your" cell system. F.e. your example with cell 37:

formulas are
y-cell = int((cell - 1)/24) +1
x-cell = ((cell-1) mod 24) +1
so...
int((37-1)/24)+1   = 2 means second row
((37-1) mod 24)+1 = 13 means 13th column


To calculate the real screen pixel position you need also to divide by 24. The INTEGER result brings you the row, the MODULO brings you the column. Because you start not with cell "0" but with cell "1" you have to substract 1 before calculating. Afterward you need to multiply by he cell size. I think it is 32? F.e. your example with cell 37:

formulas are
y-cell = int((cell - 1)/24) *32
y-cell = ((cell-1) mod 24) *32
so...
int((37-1)/24)*32   = 32 means y=32
((37-1) mod 24)*32 = 384 means x=384



If you are also interesdted to calculate the correct cell number for a given pixel-position to have to reverse the calculations

f.e. there is a bomb falling on  x=300 y= 200... Which cell is affected?

formula is:
int(y/32)*24 + int(x/32) + 1
so...
int(200/32)*24 + int(300/32) + 1
=
(6*24)  + (9) + 1 = 154  means the bomb falls into cell 154
...on the way to Egypt

Aurel [banned]

WOW
thank you very much MidiMaster
i need to read twice your explanation because i really sucks in games even such a simple
( eh simple on first look )
You must know one thing i am making this simple game in my own interpreter which
is let say limited in some things..but
so far most things work...
my arrays are indexbase 1 so my first cell is 1 not 0 .

currently i calculate sprite X cell with:
'calculate cell position using sprite upper/left pixel pos
  tmpx = int((ix + 32) / 32)

here is current program( sorry if look strange )
it is pure GDI graphic
'gdi 2d platformer example
ptr img0,img1,img2,img3
ptr wmKeyDown
var wp,ix,iy,p,ex,ey,lx,ly,bx,by,cell, tmpx,tmpy
wcolor 0,0,0:swap
'syntax-> LoadImg (1)hImg , (3)str "img.bmp" ,(5)imgType , (7)w , (9)h, (11)colorFlags

'load another image
'LoadImage(0, strRes, imgType, imgW, imgH, cFlag)
LoadImg img0,"cells.bmp"  ,0, 785,482, 24
'green blocks
LoadImg img1,"leaf.bmp"  ,0, 32,32, 16
'print 10,200,img1
LoadImg img2,"player4.bmp",0, 32,32, 24
'print 10,250,img2
LoadImg img3,"shadow.bmp",0, 32,32, 24
'print 10,300,img3
'ShowImgT img3,300, 300, 40, 40
info()



ex = 300 : ey = 300

'call intro screen
'LoadCells()

'events...
WinMsg wmKEYDOWN

hWparam wp
'vkLEFT -----------------------------------
if wp = 37
   if ix > 0 : ix = ix - 32
      fcolor 0,0,0 : bx = ix + 32 : by = iy
   endif
endif

'vkRIGHT ?----------------------------------
if wp = 39
   if ix < 736 : ix = ix + 32 : endif
endif

'vkUP --------------------------------------
if wp = 38
     if iy > 0 : iy = iy - 32 :endif
endif

'vkDOWN --------------------------------------
if wp = 40
    if iy < 420 : iy = iy + 32 :endif
endif

while wp ! 27

    updateBack() 
    updatePlayer()
    updatePosition()
    'updateBullet()
    'updateEnemy()
    'testCollision()
    'delay loop
   '  p=0
   ' while p < 800
    ' p=p+0.01
   'wend
swap

wend

EndWm

func updatePosition()
   fcolor 80,80,100    : rect 524,512,68,24   
   fcolor 100,160,220  : print 530,514,ix
   fcolor 80,80,100    : rect 610,512,68,24
   fcolor 100,160,220  : print 612,514,iy
   'calculate cell position using sprite upper/left pixel pos
   tmpx = int((ix + 32) / 32)
   
   fcolor 180,100,50  : rect 406,512,68,24 : print 410,514, tmpx

endfn
'----------------------------------------
func updateBack()
ShowImgT img0,0,0,785,482
endFn
'----------------------------------------
func updatePlayer()
  ShowImgT img2,ix,iy,32,32 
endFn
'-----------------------------------------
func updateEnemy()
   if ex < 600 : ex = ex + 1 : endif
   if ex = 598 : ex = 10 : endif
   fcolor 0,0,0 : rect 0,0,800,512
   ShowImgT img3, ex, ey, 40, 40
swap
endfn

func updateLeaf()
   ShowImg img1,0,0,32,32 : showImgT img3,bx,by,32,32
endFn

'*********************************************
'***  I N T R O ******************************
'*********************************************
func info()
'clear screen
fcolor 0,0,0 : rect 6,518,200,32 :

fcolor 200,180,100: print 10,520,"GDI Intro by Aurel"

swap
endfn

func LoadCells() 
    ShowImgT img0, 0,0, 785,482
endFn




(Y)

Aurel [banned]

MidiMaster
is it smart to do it on this way ?
and how fast that would be ?
As you may see from above image i can move my player sprite around window
I was thinking about something simple

f.e. add bricks or blocks that player can move around but not trough blocks
i think that i need to post image
(Y)

Midimaster

#7
I immediately thought that you try to do this in a limited interpreter which only knows 1-dimensional arrays.

So your way to do it, is absolutely smart, because it leads to the result you want to reach. This will have no disadvange in speed.
Basically all  (also multi-dinsional) arrays are "1-dimensional" because the RAM is also only a 1-dimensional queue of Bytes. The multi-dimensional arrays only have a "transfer-function" to calculate the 2 values of a 2-dim-array into a RAM offset.

1-dim array with 5 elements needs 5 RAM places:
1-2-3-4-5

2-dim array with 3x5 elements need 15 RAM places:
A1-A1-A3-A4-A5-B1-B1-B3-B4-B5-C1-C1-C3-C4-C5




Quote....currently i calculate sprite X cell with:
'calculate cell position using sprite upper/left pixel pos
  tmpx = int((ix + 32) / 32)...
this is the same formula like my...
int(x/32) + 1

that what I called reverse calculation: you want to know the cell for a given pixel-coordinate. Your example is only doing it for the x coordinate. so this leads always to the cells 1-24 only. You need a second part to integrate the y-value:

cell= int(y/32)*24 + int(x/32) + 1

If you are able to write functions in your interpreter I would recommend to write a function that takes a coordinate pair and return the cell number:


Function WhichCellIsAt:Int(ScreenY:Int, ScreenY:Int)
     Return int(ScreenY/32)*24 + int(ScreenX/32) + 1
End Function


...on the way to Egypt

Aurel [banned]

#8
hi midimaster

and thanks again ..i hope that i understand whole concept better
then when i started to do this.

QuoteIf you are able to write functions in your interpreter
I would recommend to write a function that takes a coordinate pair and return the cell number:

Function WhichCellIsAt:Int(ScreenY:Int, ScreenY:Int)
     Return int(ScreenY/32)*24 + int(ScreenX/32) + 1
End Function


Well i don't have yet userDfined functions (with arguments)
but i have subroutines called func() as you may see from code

so can i maybe add built-in function like old
zxSpectrum have ..i think that was called SCREEN$(x,y)

for example :

if i made it like CELL (spriteH, spriteX,spriteY , res )

res variable can be Boolean or Integer which hold TRUE or FALSE
or something similar?
(Y)

Midimaster

#9
if the interpreter does not know "functions with parameters" you can simulate this by always use the same global variables:

Function WhichCellIsAt:Int(ScreenY:Int, ScreenY:Int)
     Return int(ScreenY/32)*24 + int(ScreenX/32) + 1
End Function


' becomes to....


'define 3 variables for func communication:
var funcX, funcY, funcReturn
....

' set them when you want to call the function
funcX = SpriteX : funcY = SpriteY
WhichCellIsAt()
'and afterwards get back the result:
MyCell = funcReturn


'now the same for another situation. For f.e. a stone....
funcX = StoneX : funcY = StoneY
WhichCellIsAt()
'and afterwards get back the result:
StoneCell = funcReturn

....

' here is the function:
Func WhichCellIsAt()  ' needs 3 variables IN: funcX, funcY  OUT: funcReturn
     funcReturn =  INT(funcY/32)*24 + INT(funcX/32) + 1
End Function




Sorry... I don not understand what you mean here:


Quote....so can i maybe add built-in function like old
zxSpectrum have ..i think that was called SCREEN$(x,y)

for example :

if i made it like CELL (spriteH, spriteX,spriteY , res )

res variable can be Boolean or Integer which hold TRUE or FALSE
or something similar?...
...on the way to Egypt

steve_ancell

#10
@Aurel: Is this what you're after?



// Project: Game
// Created: 22-06-02

// show all errors

SetErrorMode(2)

// set window properties
SetWindowTitle( "Game" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 )




gosub SetGlobals


do
    DrawGrid()
    ShowInfo()
   
    Sync()
   
loop




SetGlobals: // Set up some variables
global columnCount as integer = 20
global rowCount as integer = 16
global cellWidth as integer = 40
global cellHeight as integer = 40

return




function DrawGrid()
local text as integer
local colour as integer

text = CreateText("") // A text object for putting address info inside the grid cells
colour = MakeColor(105, 105, 255) // Colour for the grid lines

for row = 0 to rowCount // Iterate through the rows
for col = 0 to columnCount // Iterate through the columns
x = cellWidth * col // Horizontal position of current cell
y = cellHeight * row // Vertical position of current cell

arrayAddress = GetArrayAddress(col, row) // Get linear address of the current cell

DrawBox(x, y, cellWidth, cellHeight, colour, colour, colour, colour, 0) // Draw the current cell

if col < columnCount and row < rowCount // Show the lenear address inside of the current cell if within boundary
SetTextString(text, str(arrayAddress))
SetTextSize(text, 25)
SetTextPosition(text, x, y)
DrawText(text)

endif

next col

next row

DeleteText(text) // Delete the text object when all lenear addresses have been displayed

endfunction


function GetArrayAddress(col as integer, row as integer)
local index as integer
index = (columnCount * row) + col // This is the important bit that gets the linear address from the column and row postion

endfunction index


function ShowInfo() // Display the result
local text as integer

col = floor(GetPointerX() / cellWidth)
row = floor(GetPointerY() / cellHeight)
text = CreateText("")

SetTextSize(text, 25)

if col < columnCount and row < rowCount
SetTextString(text, "Column: " + str(col))
SetTextPosition(text, 820, 240)
DrawText(text)

SetTextString(text, "Row: " + str(row))
SetTextPosition(text, 820, 270)
DrawText(text)

SetTextString(text, "Array Address: " + str(GetArrayAddress(col, row)))
SetTextPosition(text, 820, 300)
DrawText(text)

endif

DeleteText(text)

endfunction


steve_ancell

I know my previous comment is AGK but you should be able to make it work with what ever devkit you're using.

Aurel [banned]

ahh Steve thanks

midimaster

i mean if i create in my interpreter  let say :

new comand

CELL (spriteH, spriteX,spriteY , res )

spriteH - should be  sprite handler variable
res      - should  be TRUE or FALSE or  1 /0       depending is sprite
on a tested location

or i complicate this time ...?
(Y)

Aurel [banned]

i think that your method should work

here is the function:
Func WhichCellIsAt()  ' needs 3 variables IN: funcX, funcY  OUT: funcReturn
     funcReturn =  INT(funcY/32)*24 + INT(funcX/32) + 1
End Function
(Y)