NaaLaa
Pixel Collision - Printable Version

+- NaaLaa (https://www.naalaa.com/forum)
+-- Forum: NaaLaa (https://www.naalaa.com/forum/forum-1.html)
+--- Forum: NaaLaa 7 Questions (https://www.naalaa.com/forum/forum-3.html)
+--- Thread: Pixel Collision (/thread-113.html)

Pages: 1 2


Pixel Collision - johnno56 - 04-09-2024

I figured that I might try some 'old school' collision detection...

The concept is... A falling box. An area to land on. Using the 'pixel()' command, instruct the box to stop, as it "hits" the ground.

In this example, I am testing the pixel below the box's left bottom edge. (I have placed a reference pixel under the box at the same "y" co-ordinate.)

Press SPACE to drop...

Code:
' Open a window and enable double buffering.
set window "Pixel Collision", 640, 480
set redraw off

visible Box = [255, 255, 0, 64]
visible BoxW = 32
visible BoxH = 48
visible BoxX = (width(primary) - BoxW) / 2
visible BoxY = 0
visible vSpeed = 0
visible drop = false

visible ground = [0, 255, 0]

do

    set color 0, 0, 0
    cls
   
    Update()
    Draw()
   
    redraw
    fwait 30
   
until keydown(KEY_ESCAPE, true)

function Update()
    '   vSpeed
    if keydown(KEY_SPACE, true)     drop = true
    if drop = true  vSpeed = vSpeed + 0.03
   
    '   Box
    BoxY = BoxY + vSpeed
   
    '   Pixel Collision
    if pixel(BoxX, BoxY + BoxH) = ground
        vSpeed = 0
    endif
   
    '   Just in case 'pixel' fails... lol
    if BoxY > height(primary)
        vSpeed = 0
        wait 1000
        end
    endif
endfunc

function Draw()
    '   Ground
    set color ground
    draw rect 0, 460, 640, 20, 0
   
    '   Box
    set color Box
    draw rect BoxX, BoxY, BoxW, BoxH, 0
   
    '   Pixel
   
    '   This indicator pixel is drawn one pixel below the box center.
    '   The actual pixel being tested is below the left corner of the box.
    set color 255, 0, 255
    draw pixel BoxX + 15, BoxY + BoxH
endfunc

Unfortunately this did not work... "Read the manual", I hear you say... "pixel(x,y) Returns the color at position (x, y) as an array [r, g, b, a] with RGBA intensities in the range [0 .. 255].

I am hoping that my programing skills are the source of the problem otherwise this maybe another "can of worms".... sorry...


RE: Pixel Collision - johnno56 - 04-09-2024

I figured that I would test the pixel detection using RCBasic... Apart from running much slower, not only did I convert the program correctly, I also recreated the same result. Logic would seem to dictate that it would be highly unlikely that two different programing languages would experience the same error, N7 using pixel() and RC using getPixel()... I am left with no other explanation except for 'programmer error'...

So much for that idea... moving on... lol


RE: Pixel Collision - 1micha.elok - 04-09-2024

(04-09-2024, 11:25 AM)johnno56 Wrote: I figured that I would test the pixel detection using RCBasic... Apart from running much slower, not only did I convert the program correctly, I also recreated the same result. Logic would seem to dictate that it would be highly unlikely that two different programing languages would experience the same error, N7 using pixel() and RC using getPixel()... I am left with no other explanation except for 'programmer error'...

So much for that idea... moving on... lol

PIXEL COLLISION
       
click on each image to zoom in

Please try this code in N7
Code:
'----------------
' INITIALIZATION
'----------------
set window "Pixel Collision", 640, 480
set redraw off

'color definition
white       = [255,255,255]
black       = [0,0,0]
green       = [0,255,0]

'Box
box = []
box.w       = 32
box.h       = 48
box.x       = (width(primary)-box.w)/2
box.y       = 0
box.speed   = 0
box.drop    = false

'Ground
ground      = []
ground.x    = 0
ground.y    = height(primary)/2
ground.w    = 640
ground.h    = 60

'Get color by Pixel()
getcolor    = []

'-----------
' MAIN LOOP
'-----------
do
    'clear screen
    set color black;cls; set color white
   
    'box movement   
    if keydown(KEY_SPACE, true) then box.drop = true
    if box.drop = true  then
        box.speed = box.speed + 0.03
    else
        box.speed = 0
    endif
    box.y = box.y + box.speed
   
    'draw green ground and white box
    set color green; draw rect ground.x,ground.y,ground.w,ground.h,1
    set color white; draw rect box.x,box.y,box.w,box.h,1
   
    'collision detection by Pixel()
    getcolor = pixel(box.x,box.y+box.h)
    if getcolor[0]=green[0] and getcolor[1]=green[1] and getcolor[2]=green[2] then
        box.drop = false
    endif 

    'info
    set caret width(primary)/2,height(primary)-50;center "Press SPACE BAR to drop the white box"
                                   
    redraw
    fwait 30   
until keydown(KEY_ESCAPE, true)



RE: Pixel Collision - johnno56 - 04-09-2024

So... in a nutshell... because the colours are defined as a table, each element of the table, must detect the collision colour in order to function correctly?

Oh... Just for giggles... Instead of using filled rectangles, just use unfilled rectangles, then let me know if you get the same results as I?


RE: Pixel Collision - 1micha.elok - 04-10-2024

(04-09-2024, 06:21 PM)johnno56 Wrote: So... in a nutshell... because the colours are defined as a table, each element of the table, must detect the collision colour in order to function correctly?

Oh... Just for giggles... Instead of using filled rectangles, just use unfilled rectangles, then let me know if you get the same results as I?

Pixel Collision v2 - Unfiled rectangle

           
click each image to zoom in

Code:
'----------------
' INITIALIZATION
'----------------
set window "Pixel Collision v2", 640, 480
set redraw off

'color definition
white       = [255,255,255]
black       = [0,0,0]
green       = [0,255,0]

'Box
box = []
box.w       = 32
box.h       = 48
box.x       = (width(primary)-box.w)/2
box.y       = 0
box.speed   = 0
box.drop    = false

'Ground
ground      = []
ground.x    = 0
ground.y    = height(primary)/2
ground.w    = 640
ground.h    = 60

'Get color by Pixel()
getcolor    = []
startscreen = true

'-----------
' MAIN LOOP
'-----------
do
    'clear screen
    set color black;cls; set color white
    if startscreen then
        message = "Press SPACE BAR to drop the box"
        startscreen = false
    endif
       
    'box movement   
    if keydown(KEY_SPACE, true) then box.drop = true
    if box.drop = true  then
        box.speed = box.speed + 0.03
        message = "the box is falling..."
    else
        box.speed = 0
    endif
    box.y = box.y + box.speed

    'info
    set caret width(primary)/2,height(primary)-50;center message   
         
    'draw green ground and white box
    set color green; draw rect ground.x,ground.y,ground.w,ground.h,1
    set color white; draw rect box.x,box.y,box.w,box.h
   
    'collision detection by Pixel()
    getcolor = pixel(box.x,box.y+box.h)
    if getcolor[0]=green[0] and getcolor[1]=green[1] and getcolor[2]=green[2] then
        box.drop = false
        message = "the box is on the ground"
    endif 
                                   
    redraw
    fwait 30   
until keydown(KEY_ESCAPE, true)



RE: Pixel Collision - johnno56 - 04-10-2024

Here is something funny... change the 'green' box to 'empty' and see if the white box passes through the "top" of the green box but lands on the "bottom" of the green box... lol

Having a "filled" green box will be the way to go... chances are I will not require a "wireframe" landing area.

Nicely done!

By the way... If you get a chance... display the value of "getcolor" somewhere "out of the way" on the screen. For example: set caret 0, 50; wln str(getcolor)
Even without pressing any keys, watch the value "tick over"... I think this may have something to do with the "garbage" that Marcus mentioned being collected when using the pixel() command... I could be wrong... But it is funny that the value of getcolor is changing even though the white box does not move... weird huh?

I would imagine that this is one of the advantages of using the Tilemap Editor... All the collision nonsense is taken care of...

Time for lunch... Have a great day!


RE: Pixel Collision - 1micha.elok - 04-10-2024

(04-10-2024, 02:26 AM)johnno56 Wrote: Here is something funny... change the 'green' box to 'empty' and see if the white box passes through the "top" of the green box but lands on the "bottom" of the green box... lol
...

Time for lunch... Have a great day!

It's fun to play around and to explore different kind of variables (filed, unfiled/empty, box, ground) ... or even to use simple kind of physics
- the box bounce / rebound after hitting the ground
- the box lose its balance and fall on one of its side to the ground

Have a great day, too


RE: Pixel Collision - kevin - 04-10-2024

(04-10-2024, 03:22 AM)1micha.elok Wrote:
(04-10-2024, 02:26 AM)johnno56 Wrote: Here is something funny... change the 'green' box to 'empty' and see if the white box passes through the "top" of the green box but lands on the "bottom" of the green box... lol
...

Time for lunch... Have a great day!

Hi, I think this issue may be because you are using a floating point number for box.y. If you change the line where you increase this value each cycle to the following, the issue of falling through the top line disappears:

Code:
box.y = int(box.y + box.speed) 

It may however then cause issues if box.speed becomes greater than one. One way to workaround that would be to use:
Code:
box.y = int(box.y + min(box.speed,1))

This limits box.speed to 1, so may be too slow for your needs. I'm sure there will be ways round this if needed.

All the best - Kevin.


RE: Pixel Collision - 1micha.elok - 04-10-2024

(04-10-2024, 06:52 AM)kevin Wrote: Hi, I think this issue may be because you are using a floating point number for box.y. If you change the line where you increase this value each cycle to the following, the issue of falling through the top line disappears:

Code:
box.y = int(box.y + box.speed) 

...

It's solved ! Thank you, Kevin

   
click the image to zoom in


RE: Pixel Collision - johnno56 - 04-11-2024

Ok. Here is a preliminary test. No sounds; No HUD; No animations.

The ship starts "off screen" at a random "x" position. Use arrow keys to land the ship. Warning: there are no fuel limits (yet) and no "rapid landing" sensors (yet). "BOTH" landing struts MUST land on the Pad to complete the game. One strut on the Pad or either strut touches the ground... BOOM!

Note: I use two collision points. The outer corner of each strut base.

Couple of things I have noticed using the "pixel detection method": 1. Controlling the ship is not as "smooth" as I would normally like and 2. Pixel() does NOT work when the ship is off the screen. I have had to restrict the "sensing" for when the ship is visible.

Other than that, it is what it is... a concept for a game. Any suggestions (positive) are always appreciated....


.zip   pixelCollision3.zip (Size: 25.93 KB / Downloads: 4)

J