Murga-Projects Forums

Full Version: PONG
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Here's version one of a one player Pong.
Move the mouse up and down to control both paddels.
The ball speed increases up to a point each time its hit by a paddle or a the left and right sides.

I've attached the Fluid file.

Code:
math.randomseed(os.time())
bvx=math.random(1,2)
bvy=math.random(1,2)-1
leftscore=0
rightscore=0
ballspeed=2
maxballspeed=9
ballspeedinc=0.2
playGame=true
oldTime=os.time()
--total distance per second
tdx,tdy= 0,0
--inrect
function inrect(x,y,xx,yy,xxx,yyy)
if x>=xx and x<=xxx and y>=yy and y<=yyy then return true end
return false
end
--ballspeedup
function ballspeedup()
if ballspeed < maxballspeed then ballspeed=ballspeed+ballspeedinc end
end
--borderball detects border hit
function borderball()
bx,by=Ball:x(),Ball:y()
bxx,byy=bx+16,by+16
borderhit=false


-- if the ball exits  the gamefield then reset to center
if inrect(bx,by,fx,fy,fxx,fyy) ~= true and inrect(bxx,byy,fx,fy,fxx,fyy) ~= true then
bx,by = (FIELDBOX:w()/2)+1,(FIELDBOX:h()/2)+1
Ball:resize(bx,by,16,16)
end

--if the ball is beyond the left side of the field, reverse x direction
    if bx <=fx then
    bvx=1
    borderhit=true
    rightscore=rightscore+1
    SCORERIGHT:value(rightscore)
    ballspeedup()
    end
--if the ball is beyond the right side of the field, reverse x direction
    if bxx >= fxx then
    bvx=-1
    
    leftscore=leftscore+1
    SCORELEFT:value(leftscore)
    ballspeedup()
    end
    
--if the ball hits the top of the field then reverse direction
        if by <=fy then
        bvy=1
        ballspeedup()
        Ball:labelcolor(95)
        end
        
--if the ball hits the bottom of the field  reverse direction        
    if  byy >= fyy then
    bvy=-1
    ballspeedup()
    Ball:labelcolor(95)
    end
    
    if borderhit == true then
    bvy=math.random(1,2)
    if bvy==2 then
        bvy=1
        else
        bvy=-1
        end                
    end
    

        
return bvx,bvy
end
--blockball
function blockball(px,py,pxx,pyy)
bx,by=Ball:x()+bvx,Ball:y()+bvy
bxx,byy=bx+16,by+16

--if the ball is still in the field then detect block hits
if inrect(bx,by,px,py,pxx,pyy) == true or inrect(bxx,byy,px,py,pxx,pyy) == true then

--if the ball is on the left side of the field
    if bx <= (FIELDBOX:w()/2) then
    bvx=1
    Ball:labelcolor(80)
    --or if its on the right side
    else
    bvx=-1
    Ball:labelcolor(220)
    end
        
    

            
byr=math.random(1,15)

        if byr <= 5 then bvy=0 end
        if byr  >= 6 and byr <= 10 then bvy=-1 end
        if byr >= 11 then bvy=1 end  
    
end

end
-- moveBall
function moveBall()
-- move the ball

bx,by = Ball:x(),Ball:y()
obx,oby = bx,by
bx=bx+bvx*ballspeed
by=by+bvy*ballspeed
Ball:resize(bx,by,16,16)
    
    --total distance
    tdx=tdx+(math.abs(bvx)*ballspeed)
    tdy=tdy+(math.abs(bvy)*ballspeed)
    if os.time()-oldTime >= 1 then
    distance:label("distance per second x:"..tdx.."  y:"..tdy)
    tdx,tdy= 0,0
    oldTime=os.time()
    end
end
-- movePaddles
function movePaddles()
mx=Fl:event_x()
my=Fl:event_y()

lx,ly=LEFTBOX:x(),LEFTBOX:y()
lxx,lyy=lx+LEFTBOX:w(),my+LEFTBOX:h()
if inrect(mx,my,fx,fy,fxx,fyy) == true and inrect(mx,lyy,fx,fy,fxx,fyy) == true then
LEFTBOX:resize(lx,my,LEFTBOX:w(),LEFTBOX:h())
end

rx,ry=RIGHTBOX:x(),RIGHTBOX:y()
rxx,ryy=rx+RIGHTBOX:w(),my+RIGHTBOX:h()

if inrect(mx,my,fx,fy,fxx,fyy) == true and inrect(mx,ryy,fx,fy,fxx,fyy) == true then
RIGHTBOX:resize(rx,my,RIGHTBOX:w(),RIGHTBOX:h())
end


lx,ly=LEFTBOX:x(),LEFTBOX:y()
lxx,lyy=lx+LEFTBOX:w(),my+LEFTBOX:h()
rx,ry=RIGHTBOX:x(),RIGHTBOX:y()
rxx,ryy=rx+RIGHTBOX:w(),ry+RIGHTBOX:h()
blockball(lx,ly,lxx,lyy)
blockball(rx,ry,rxx,ryy)

end
--playPong
function playPong()

if (Fl:event_text()== "q") then os.exit() end

speedkey=tonumber(Fl:event_text())
if speedkey ~= nil then
if speedkey >= 1 and speedkey <=9 then ballspeed=speedkey end
    end     
         
         if playGame == true then
         
     movePaddles()
     borderball()
     moveBall()
    
        Pong:redraw()
       -- adjust murgaLua.sleepMilliseconds  for speed
       -- murgaLua.sleepMilliseconds(20)
    end
end
--pongWindow_CB
function pongWindow_CB()

if (Fl:event_key()== fltk.FL_Escape) then playGame=not playGame end
    
    if playGame == true then
    Pong:label("PONG")
    else
    Pong:label("PONG  (PAUSED)")
    end
end

do Pong= fltk:Fl_Double_Window(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "PONG")
Pong:label(gLabelTable[#gLabelTable])
Pong:callback(pongWindow_CB)
Pong:resize(380,194,652,443)
Pong:color(0)

do FIELDBOX= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "FIELDBOX")
FIELDBOX:label(gLabelTable[#gLabelTable])
FIELDBOX:resize(0,0,655,444)
FIELDBOX:box(fltk.FL_FLAT_BOX)
FIELDBOX:color(0)
FIELDBOX:labeltype(fltk.FL_NO_LABEL)
FIELDBOX:labelcolor(33)
end

do SCORELEFT= fltk:Fl_Output(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "SCORELEFT")
SCORELEFT:label(gLabelTable[#gLabelTable])
SCORELEFT:resize(205,1,60,51)
SCORELEFT:box(fltk.FL_NO_BOX)
SCORELEFT:color(0)
SCORELEFT:labeltype(fltk.FL_NO_LABEL)
SCORELEFT:labelsize(7)
SCORELEFT:labelcolor(72)
SCORELEFT:textsize(36)
SCORELEFT:textcolor(72)
end

do SCORERIGHT= fltk:Fl_Output(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "SCORERIGHT")
SCORERIGHT:label(gLabelTable[#gLabelTable])
SCORERIGHT:resize(385,0,65,51)
SCORERIGHT:box(fltk.FL_NO_BOX)
SCORERIGHT:color(0)
SCORERIGHT:selection_color(177)
SCORERIGHT:labeltype(fltk.FL_NO_LABEL)
SCORERIGHT:labelsize(7)
SCORERIGHT:labelcolor(72)
SCORERIGHT:textsize(36)
SCORERIGHT:textcolor(177)
end

do LEFTBOX= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "LeftBox")
LEFTBOX:label(gLabelTable[#gLabelTable])
LEFTBOX:resize(25,193,24,82)
LEFTBOX:box(fltk.FL_FLAT_BOX)
LEFTBOX:color(80)
LEFTBOX:labeltype(fltk.FL_NO_LABEL)
LEFTBOX:labelsize(7)
LEFTBOX:labelcolor(88)
end

do RIGHTBOX= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "Rightbox")
RIGHTBOX:label(gLabelTable[#gLabelTable])
RIGHTBOX:resize(600,193,24,82)
RIGHTBOX:box(fltk.FL_FLAT_BOX)
RIGHTBOX:color(220)
RIGHTBOX:labeltype(fltk.FL_NO_LABEL)
RIGHTBOX:labelsize(7)
RIGHTBOX:labelcolor(216)
end

do instructions= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "ESC to Pause   Q to QUIT")
instructions:label(gLabelTable[#gLabelTable])
instructions:resize(0,-1,650,16)
instructions:labelsize(10)
instructions:labelcolor(63)
end

do distance= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "distance per second")
distance:label(gLabelTable[#gLabelTable])
distance:resize(0,427,650,16)
distance:labelsize(10)
distance:labelcolor(63)
end

do Ball= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "¥")
Ball:label(gLabelTable[#gLabelTable])
Ball:resize(320,226,15,16)
Ball:labelsize(16)
Ball:labelcolor(95)
end
end
Pong:show()

gLabelTable[#gLabelTable] ="@circle"
Ball:label(gLabelTable[#gLabelTable])

Pong:make_current();
fx,fy=FIELDBOX:x()+8,FIELDBOX:y()+8
fxx,fyy=fx+FIELDBOX:w()-8,fy+FIELDBOX:h()-8

while Pong do
Fl:check()
playPong()    
end
Fl:run()

Looks appealing, but doesn't work properly for me. The ball (is it supposed to be a Yen symbol, or is my encoding wrong?) goes way too fast, and the paddles don't respond most of the time.

I assume pongWindow_CB is supposed to toggle gameplay. On my system, the gameplay stops after pressing Esc several times, and then instead of resuming it resumes for what is apparently one loop and stops again.

It might be useful to have a button or two, particularly a quit button. There seems to be an increasing number of Linux users lately with window managers like mine that don't have min/max/close buttons (dwm, xmonad, awesome).
The mouse won't move the paddles unless the pointer is inside the window.
I tried ignoring at least the mouse X but found as soon as the paddle leaves the window, the program doesn't catch the mouse values.

I've set the ballspeedinc=0.2, it speeds up half as fast as last time.
Maxspeed is 9 now to match the keyboard. Keys 1 through 9 will set the current ball speed.
Q key will quit. Escape key should properly toggle Pause now. Added a single box of instruction for that.
The ball now changes colors on collisions.

Speed of the ball may have more to do with processor speed.
I should probably be using some increment multiplied by seconds passed
(or thousandths of a second passed) rather than absolute distances per cycle.

The ball should be the "bullet" character •, but yin-yang is cool to ;-).


Code and Fluid file updated in original post.
Behaves a little better, but still speeds up quickly to a ridiculous pace, and paddles not responding most of the time.

I'm supposing it's not catching mouse movement or key presses unless they occur at a specific point in the loop. When I press a key, it takes a few seconds before it registers.

I replaced the Yen character with a FLTK square label (it was Yen in my browser, so that's how it copied into Vim).
Was this: table.insert(gLabelTable, "¥")
Now this: table.insert(gLabelTable, "@-9square")
@square was much too big.
Looks cool, but isn't really usable on my system ... it seems it acts waay to fast and jerky
I see the "Ball" flashing all over the screen, and the paddles barely move.
Gamespeed depending on processorspeed sound way to much like the old DOS-games time.
Adding murgaLua.sleepMilliseconds(10) just after Pong:redraw() solves the usability issues.
Greetz,
Jan-Pieter
What speed of processor and video card are you guys working on?
I'm on 2Ghz and 128MB graphics card with unknown refresh rate.
Tested on 1.5Ghz and there wasn't really a difference.

Its really smooth here.
Any glitching from this script?
It simply has a 'ball' that follows the mouse around.
Does it go glitchy if you comment murgaLua.sleepMilliseconds(10)?

Code:
math.randomseed(os.time())
-- mouseBall
function mouseBall()
-- move the ball
bx,by = Fl:event_x(),Fl:event_y()
Ball:resize(bx,by,16,16)
end

function playMBall()
if (Fl:event_text()== "q") then os.exit() end
  mouseBall()    
  MBall:redraw()    
  murgaLua.sleepMilliseconds(10)
end

function MBallWindow_CB()
if (Fl:event_key()== fltk.FL_Escape) then playGame=not playGame end
    if playGame == true then
    MBall:label("MBall")
    else
    MBall:label("MBall  (PAUSED)")
    end
end
do MBall= fltk:Fl_Double_Window(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "MBall")
MBall:label(gLabelTable[#gLabelTable])
MBall:callback(MBallWindow_CB)
MBall:resize(380,194,652,443)
MBall:color(0)
do Ball= fltk:Fl_Box(0,0,0,0,"")
if gLabelTable==nil then gLabelTable={} end
table.insert(gLabelTable, "@-9square")
Ball:label(gLabelTable[#gLabelTable])
Ball:resize(320,226,15,16)
Ball:labelsize(50)
Ball:labelcolor(95)
end
end
MBall:show()
MBall:make_current();
while MBall do
Fl:check()
playMBall()    
end
Fl:run()



Mouse tracking is definitely not in sync.
If I turn off automatic window redrawing the ball can draw many pixels away from its last position between mouse moves.
Depends on how quickly you flick the mouse around really.
Oddly I get a different sized ball depending on if the window is redrawing or not.

Code:
function playMBall()
if (Fl:event_text()== "q") then os.exit() end
  mouseBall()
Ball:redraw()    
--this toggles window redraw, hit any other key to stop redrawing
   if (Fl:event_text()== "r") then MBall:redraw() end
--i see no effect from this, do you?
murgaLua.sleepMilliseconds(10)
end

This test works fine with or without the sleep.

The game works much better with the sleep added...unplayable without it.

I've got a 3gHz P4, and crappy onboard video (ok for most video files i've tried, but sucks for anything 3D)
Ok testresults:
- auto-redraw + sleep -> fine
- auto-redraw + no sleep -> close to a complete lockup during half a minute
- no redraw + sleep -> fine
- no redraw + no sleep -> fine, but a little more jerky.

I'm running a Dualcore 1.8GHz, intel Mobile GM965/GL960 Integrated Graphics Controller on Ubuntu 9.10.

Greetz,
JP
What does sleep do exactly.
If I set a high value like 100, I get a really slow play, but sleep 10 doesn't affect anything.

I imagine the glitchiness stems from the processor updating the movement faster than the
video card can update the screen. Just a guess. Can't seem to find any values on how fast
any video card actually updates the screen relative to how many times a loop cycles.

To keep the ball from speeding up on its own, change:
maxballspeed=9 -- to whatever you find comfortable
ballspeedinc=0.2 -- to zero if you want no auto speed increase, some

Do you still get keyboard delays with sleep?
I tried to run a test with Fl:event_text() to see what happens when you press a key.
Without the key held (and sleep 10) it returns to nil for about 20 cycles between my fastest ability to double tap it. On 3GHZ maybe its a lot more nil.
Or rather than nil, its just blank, since printing the result doesn't give the usual "nil" value Lua likes to give.

This is odd because if (Fl:event_text()== "r") then MBall:redraw() end seems to retain the
status of Fl:event_text() over time instead of only being when the key is down.

I've updated the code and Fluid in the original post.
I've added a little check and label for the total distance the ball travels.
At base speed its about 60 pixels per second and top speed its 540 per second.
sleepMilliseconds(10) doesn't appear to do anything probably because it's only 1/100 of a second...just enough to slow things down to a reasonable framerate on machines that apparently burn through the loop at an uncomfortably speedy pace (like the old DOS games JP mentioned). Raising the number to 1/10 of a second is a much more noticeable pause.

The slow response to key presses seems to be gone too. Pause and quit both work fine.

Also noticed the ball is now a ball instead of a Yen.

Only thing I'm having trouble with now is keeping my cursor inside the window.
I tried "grab", but it doesn't work as I expected it would. Also tried making the window fullscreen, but I guess that will require making all the graphic elements inside also scale with the window.
Pages: 1 2
Reference URL's