Log In  

Does print() in _update() work?

Hi there! Just purchased PICO-8 and Voxatron last week and I'm trying to recreate some classic pong action as a way of getting familiar with the ins and outs of the scripting environment (this is my first time ever interacting with anything related to Lua). Right now I've got a paddle that responds to up/down keyboard presses and a ball that bounces around the screen and collides with the paddle.

I'm trying to print some debug text at the moment of paddle + ball collision, but my print function appears to be doing nothing.

Here's what my current gameplay looks like:

And here's the code:
(the print function that appears to not be working is in line 53 - i.e. the 3rd line from the bottom)
(unrelated: sure would be nice to have line numbers on code snippets here in the forums!)

ball_x = 64
ball_y = 64
ballspeed_x = 3
ballspeed_y = 2
pad_x = 20
pad_y = 50
pad_w = 4
pad_h = 20

function _draw()
    rectfill(0,0,127,127,5)
    circfill(ball_x,ball_y,2,14)
    rectfill(pad_x, pad_y, pad_x + pad_w, pad_y + pad_h, 10)
end

function _update() 
    moveball()
    updateballcollisions()
    movepaddle()
    updatepaddlecollisions()
end

function moveball()
    ball_x += ballspeed_x
    ball_y += ballspeed_y
end

function updateballcollisions()
    if (ball_x < 0 or ball_x > 127) then
        ballspeed_x *= -1;
    end
    if (ball_y < 0 or ball_y > 127) then
        ballspeed_y *= -1;
    end
end

function movepaddle()
    if btn(2) and pad_y+(pad_h/2) > 0 then
        pad_y -= 4
    end
    if btn(3) and pad_y+(pad_h/2) < 127 then
        pad_y += 4
    end
end

function updatepaddlecollisions()
    pad_top_y = pad_y
    pad_bot_y = pad_top_y + pad_h
    pad_left_x = pad_x
    pad_right_x = pad_left_x + pad_w
    if ((ball_x > pad_left_x) and (ball_x < pad_right_x) and (ball_y > pad_top_y) and (ball_y < pad_bot_y)) then
        ballspeed_x *= -1
        print("paddle collision", 6, 6, 11)
    end
end

As you can see in the gameplay gif, my updatepaddlecollisions() function seems to be working correctly when the ball collides with the paddle except that there should also be a string "paddle collision" that prints at (6, 6) colored green (color 11), but that string never prints! :(

I'm aware of the printh() function but I'd really like to stay within the editor and just have my debug text print directly onto the app screen.

So! Am I crazy or does the print() function not work if it's in _update() or some function that gets called within _update()? Thanks so much! I'm so excited to actually build cooler things with this amazing tool!

P#68968 2019-10-17 17:52 ( Edited 2019-10-17 17:54)

1

update is called before draw
you have a fullscreen rectfill at the beginning of draw
That will clear anything on screen at this point
...

note: you can give a color to cls - no need to draw a fullscreen rect

P#68970 2019-10-17 17:57 ( Edited 2019-10-17 17:58)
1

Fred is completely right.

But to answer the question in the title: print() does work just fine in _update(). It's just that you're erasing everything it does right afterwards in _draw().

What you can do is set up a table called debug, add values you want to debug to that table in _update(), and in _draw() you print out all the contents of the table. That's a simple and flexible way to do it.

P#68975 2019-10-17 19:13

Thanks Fred and Tobias, that would explain it. But I fail to understand how cls with a color is in anyway different from drawing a default background color?
Is there a cost benefit to clearing with a color instead of drawing a background color?
Also, wouldn't a cls also clear my printed string in the same way that drawing a background color would?

The debug table is an interesting idea, but I don't like the added memory allocation.

It's good to know that the update is called before draw because the manual is really not clear about that. It states

    There are 3 special functions that, if defined by the user, are called during program 
    execution:

        _update()
            Called once per update at 30fps

        _draw()
            Called once per visible frame

        _init()
            Called once on program startup

Is the way that these are listed the order of execution? The txt file doesn't actually specify. I would assume _init() is called before _update and _draw? Usually when I script in Javascript / HTML5 I like to have my draw function called before my update, so that is a bit odd to me.

P#68978 2019-10-17 20:00 ( Edited 2019-10-17 20:01)
2

You can always code badly like I do and not even worry about _init() _draw() or _update(). :D

-- bad breakout
-- by dw817

-- player paddle starts at 10.
-- ball at 20,0.
-- acceleration down and right.
-- collision text starts off
-- the screen.
p=10 x=20 y=0 ax=2 ay=2 pc=-8

repeat ---------------------->>

-- clear screen to dark gray.
cls(5)

-- draw the player's paddle.
rectfill(12,p-7,14,p+7,10)

-- draw the ball.
circfill(x,y,2,14)

-- move the ball in the
direction chosen.
x+=ax y+=ay

-- starts out off the screen.
print("paddle collision", 6, pc, 11)

-- if it's on the screen,
-- slide it up till it's gone.
if (pc>-8) pc-=1

if x<18 and abs(y-p)<7 then
  -- if the ball hit the paddle
  -- then make the collision
  -- text visible now.
  pc=16
end

-- bounce the ball.
if (x<18 or x>127) ax=-ax
if (y<0 or y>127) ay=-ay

-- if player presses up or
-- down, move the paddle in
-- that direction.
if (btn(2)) p-=3
if (btn(3)) p+=3

-- keep  paddle on screen.
-- mid says to choose the
-- middle value. this is a good
-- way to keep a variable
-- within a range. in this
-- case, the paddle cannot go
-- lower than 7-pixels or
-- higher than 120-pixels
-- vertically.
p=mid(7,p,120)

flip()

until forever --<<-------------

Where FLIP() updates the screen and neatly waits 1/30th of a second to match the refresh rate of your screen - and that's all you need if you code this way.

Without remarks, this is pretty compact code, too.

p=10 x=20 y=0 ax=2 ay=2 pc=-8
repeat
cls(5)
rectfill(12,p-7,14,p+7,10)
circfill(x,y,2,14)
x+=ax y+=ay
print("paddle collision", 6, pc, 11)
if (pc>-8) pc-=1
if x<18 and abs(y-p)<7 then
  pc=16
end
if (x<18 or x>127) ax=-ax
if (y<0 or y>127) ay=-ay
if (btn(2)) p-=3
if (btn(3)) p+=3
p=mid(7,p,120)
flip()
until forever
P#68981 2019-10-17 20:35 ( Edited 2019-10-17 21:43)
2

@astinad: First, the file is executed by the Lua interpreter; any code that is located at the top level is executed. That means that functions get defined etc, but it also means that any oter code you have just lying around in the top level/scope is executed (you'd probably want to stick that in _init though). Then _init is called once. Then the game loop starts, which first calls _update and then _draw forever.

If _update is not defined, then _update60 is run instead, and the game loop executes 60 times a seconds instead of 30. If neither is defined, the game loop does not execute. In that case you can do like dw187 does above. It's pretty flexible. If you want to make your own game loop, you can! Just make an infinite repeat/while loop (or equivalently, like tweetcarts often do, an infinite goto loop) with a call to flip() where you want it to draw.

P#69002 2019-10-18 07:25

Thanks a lot everyone, and sorry for the late reply. This is all super helpful stuff!

P#69161 2019-10-22 07:09

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2022-12-05 23:45:16 | 0.017s | Q:15