Module pong3dgpl
[frames] | no frames]

Source Code for Module pong3dgpl

  1  # -*- coding: utf-8 -*- 
  2  """ 
  3  3dpong gameplay module - see __main__ section for demo usage 
  4   
  5  Gameplay: press SPACEBAR to launch the ball, move the mouse or use the WASD or the arrow keys or even the joystick to move the pad. A game is won by the player who  wins 2 sets more than his foe. Each set is won by the player who wons 3 rallies but gotta win 2 rallies more than his foe in case of tie score. 
  6  @author: fabius 
  7  @copyright: fabius@2010 
  8  @license: GCTA give credit to (the) authors 
  9  @version: 0.1 
 10  @date: 2010-09 
 11  @contact: astelix (U{panda3d forums<http://www.panda3d.org/forums/profile.php?mode=viewprofile&u=752>}) 
 12  @status: eternal WIP 
 13   
 14  """ 
 15  import random, sys, time 
 16  from direct.showbase.ShowBase import ShowBase 
 17  from pandac.PandaModules import * 
 18  from direct.gui.OnscreenText import OnscreenText 
 19  from direct.showbase.DirectObject import DirectObject 
 20  from direct.interval.IntervalGlobal import * 
 21  from gamelogic01 import gameplaybase 
 22  try: 
 23    from easyinput import * 
 24    _EASYINPUT=True 
 25  except ImportError: _EASYINPUT=False 
 26   
 27  #========================================================================= 
 28  # 
29 -class gameplay(gameplaybase):
30 """ Pong3D gameplay class. Derived from a generic base gameply class, this is custom-specialized to play the pong3D game. 31 """ 32 _DEBUG=False 33 PADVEL=1. 34 CPUSPD=.15 35 NPCSPD=PADVEL 36 BALLSPEED=1.0 37 BALLSPEEDMAX=2.0 38 _CPUPAD=0 39 _HUMANPAD=1 40 _SETTINGS={ 41 #MODES: '2d','3d','3dg' 42 'mode': '3dg', 43 'opponent': 'human', 44 'games': 3, 45 'sets': 3, 46 'maxfoes': 4, 47 'playernames': ['CPU0', 'Player1'] 48 } 49 _SCOREPOINTS={ 50 'rallyunit': 4, 51 'bonusunit': 100, 52 'penaltyunit': 10, 53 } 54 #----------------------------------------------------- 55 #
56 - def setcamera(self):
57 """ WARNING you actually cannot dynamically switch from 2d to 3d and vice-versa but just stay stick to one dimension or the other one 58 """ 59 if self._SETTINGS['mode'].lower().startswith('3d'): 60 # Choose a suitable pair of colors for the left and right eyes 61 leftColor = ColorWriteAttrib.CRed 62 rightColor = ColorWriteAttrib.CBlue | ColorWriteAttrib.CGreen 63 # Enable anaglyph stereo mode on the window 64 base.win.setRedBlueStereo(True, leftColor, rightColor) 65 # Remove the original, mono DisplayRegion 66 oldDr = base.cam.node().getDisplayRegion(0) 67 oldDr.setCamera(NodePath()) 68 # Create a new, stereo DisplayRegion 69 dr = base.win.makeStereoDisplayRegion() 70 dr.setCamera(base.cam) 71 # The stereo region draws the left eye, then the right eye. We need 72 # to clear the depth buffer after drawing the left eye and before 73 # drawing the right eye. 74 dr.getRightEye().setClearDepthActive(True) 75 base.camLens.setInterocularDistance(0.339) 76 77 if self._SETTINGS['mode'].lower() == '3dg': 78 dr.setStereoChannel(Lens.SCStereo) 79 else: dr.setStereoChannel(Lens.SCMono) 80 81 self.parent.cam.setPos(-25,-15,0) 82 self.parent.cam.lookAt(self.field) 83 self.parent.cam.setR(90) 84 else: 85 lens = OrthographicLens() 86 lens.setFilmSize(20, 15) 87 self.parent.cam.node().setLens(lens) 88 self.parent.cam.setY(-2)
89 90 #----------------------------------------------------- 91 #
92 - def setinputs(self):
93 if _EASYINPUT: self.si_easyinput() 94 else: self.si_noeasyinput() 95 self.parent.disableMouse() 96 if self._DEBUG: 97 self.accept('c', self.toggle_collisions) 98 self.accept('x', self.parent.toggleWireframe) 99 self.accept('o', self._setiod,[1]) 100 self.accept('p', self._setiod,[-1]) 101 self.accept('l', self._setcvd,[1]) 102 self.accept('k', self._setcvd,[-1]) 103 base.setFrameRateMeter(True)
104
105 - def si_noeasyinput(self):
106 def accepad(ks, p, v): 107 """ ease the pad key controls input setup """ 108 for k in ks: 109 self.accept(k, self.setpadvel, [p, v]) 110 self.accept('%s-up'%k, self.setpadvel, [p, 0]) 111 v=-v
112 # 113 if self._SETTINGS['mode'].lower().startswith('3d'): 114 keys=[['a', 'd'],['arrow_left', 'arrow_right']] 115 else: keys=[['w', 's'],['arrow_up', 'arrow_down']] 116 if self._SETTINGS['opponent'] <> "cpu": 117 self._SETTINGS['playernames']=['Player1','Player2'] 118 accepad(keys[0], 0, self.PADVEL) 119 accepad(keys[1], 1, self.PADVEL)
120
121 - def si_easyinput(self):
122 # 123 cfg="" 124 ibridge={} 125 if self._SETTINGS['mode'].lower().startswith('3d'): 126 cfg+=""" 127 bind a "pad0up" 128 bind d "pad0down" 129 bind arrow_up "" 130 bind arrow_down "" 131 bind arrow_left "pad1up" 132 bind arrow_right "pad1down" 133 bind mouse-x "mousemove" 134 """ 135 else: 136 cfg+=""" 137 bind w "pad0up" 138 bind s "pad0down" 139 bind arrow_up "pad1up" 140 bind arrow_down "pad1down" 141 bind arrow_left "" 142 bind arrow_right "" 143 """ 144 if self._SETTINGS['opponent'] <> "cpu": 145 ibridge['pad0up']=lambda v,p=0: self.xsetpadvel(p,v) 146 ibridge['pad0down']=lambda v,p=0: self.xsetpadvel(p,-v) 147 else: 148 ibridge['heading']=lambda v,p=0: self.xsetpadvel(p,v) 149 ibridge['pad1up']=lambda v,p=1: self.xsetpadvel(p,v) 150 ibridge['pad1down']=lambda v,p=1: self.xsetpadvel(p,-v) 151 ibridge['mousemove']=lambda v,p=1: self.xsetpadvel(p,-v) 152 153 self.xinput=easyinput(cfg, ibridge, debug=False)
154
155 - def xsetpadvel(self,a,b):
156 self.setpadvel(a,b)
157
158 - def _setiod(self, v=0):
159 d=.05 160 v=base.camLens.getInterocularDistance()+(v*d) 161 base.camLens.setInterocularDistance(v) 162 self.dbgprint("IOD:%r"%base.camLens.getInterocularDistance())
163 - def _setcvd(self, v=0):
164 d=.1 165 v=base.camLens.getConvergenceDistance()+(v*d) 166 base.camLens.setConvergenceDistance(v) 167 self.dbgprint("CVD:%r"%base.camLens.getConvergenceDistance())
168 169 #----------------------------------------------------- 170 #
171 - def setscene(self):
172 if self._SETTINGS['opponent'] <> "cpu": 173 self._SETTINGS['playernames']=['Player1','Player2'] 174 # 175 self.field=loader.loadModel('pong3d') 176 self.field.setScale(10) 177 self.field.reparentTo(self.parent.render) 178 self.parent.cam.lookAt(self.field) 179 # 180 self.lights=[] 181 # Create Ambient Light 182 lv=.3 183 ambientLight = AmbientLight('ambientLight') 184 ambientLight.setColor(Vec4(lv, lv, lv, 1)) 185 ambientLightNP = self.parent.render.attachNewNode(ambientLight) 186 self.lights.append(ambientLightNP) 187 self.parent.render.setLight(ambientLightNP) 188 # Directional light 01 189 lpos=(-4, -6, 2) 190 lv=.7 191 directionalLight = DirectionalLight('directionalLight') 192 directionalLight.setColor(Vec4(lv, lv, lv, 1)) 193 directionalLightNP = self.parent.render.attachNewNode(directionalLight) 194 directionalLightNP.setPos(lpos) 195 directionalLightNP.lookAt(self.field) 196 self.lights.append(directionalLightNP) 197 self.parent.render.setLight(directionalLightNP) 198 199 font=loader.loadFont("data/fonts/slkscre.ttf") 200 font.setMagfilter(Texture.FTNearest) 201 self.text={ 202 'score': OnscreenText(fg=(1,1,1,1), font = font, 203 text = '', pos = (0, .75), scale = 0.3, mayChange=True, 204 ), 205 'sets': OnscreenText(fg=(1,1,1,1), font = font, 206 text = '', pos = (0, .65), scale = 0.08, mayChange=True, 207 ), 208 'cmsg': OnscreenText(fg=(1,1,1,1), font = font, 209 text = '', pos = (.0, .0), scale = 0.3, mayChange=True, 210 ), 211 }
212 213 #----------------------------------------------------- 214 #
215 - def setgame(self):
216 self.pad=[] 217 for i in range(2): 218 self.pad.append({}) 219 self.pad[i]['name']=self._SETTINGS['playernames'][i] 220 self.pad[i]['totrly']=0 221 self.pad[i]['totgam']=0 222 self.pad[i]['gam']=0 223 self.pad[i]['set']=0 224 self.pad[i]['vel']=0 225 self.pad[i]['mdl']=self.field.find("**/pad%d"%i) 226 self.pad[i]['mdl'].setBin('fixed', 40) 227 228 self._collphysetup() 229 # n items deve corrispondere a maxfoes+1 230 self._BOTS=[self.bot0, self.bot0, self.bot1, self.bot1, self.bot1] 231 self.actualbot=self._BOTS[0] 232 233 self.maintask = None 234 self.npctask=None 235 self.setmaintask(1) 236 237 self.playerturn=random.choice(range(2)) 238 self.updatescore() 239 self.ballreset()
240 241 #----------------------------------------------------- 242 #
243 - def setmaintask(self, on):
244 if on: 245 if not self.maintask: 246 self.maintask = taskMgr.add(self.mainloop, "gpl01_main", priority = 35) 247 self.maintask.last = 0 248 if self._SETTINGS['opponent'] == "cpu": 249 self.npctask = taskMgr.doMethodLater(self.CPUSPD, self.npcloop, 'gpl01_npctsk') 250 else: self.npctask=None 251 else: 252 if self.maintask: 253 taskMgr.remove(self.maintask) 254 self.maintask=None 255 if self._SETTINGS['opponent'] == "cpu": taskMgr.remove(self.npctask)
256 257 #----------------------------------------------------- 258 #
259 - def onfinish(self):
260 self.xinput.finish() 261 self.parent.physicsMgr.clearPhysicals() 262 self.parent.cTrav.clearColliders() 263 self.field.removeNode() 264 for t in self.text: self.text[t].destroy() 265 for l in self.lights: self.parent.render.clearLight(l)
266 267 #----------------------------------------------------- 268 #
269 - def mainloop(self, task):
270 dt = task.time - task.last 271 task.last = task.time 272 for i in range(2): 273 padvel=self.pad[i]['vel'] 274 if padvel: 275 pad=self.pad[i]['mdl'] 276 z=pad.getZ()+(padvel*dt) 277 z=max(min(z, self.PADLIMZ), -self.PADLIMZ) 278 pad.setZ(z) 279 # check ball off the wall boundaries 280 if ( 281 (abs(self.ball.getPosition()[2]) > .75) or 282 (abs(self.ball.getPosition()[0]) > 1.08) 283 ): 284 self.playerscore(self.ball.getPosition()[0] > 0) 285 return task.cont
286 287 #----------------------------------------------------- 288 #
289 - def _centerpad(self, padz):
290 v=0. 291 if abs(padz) > random.uniform(.0, .06): v=-1. if padz > 0. else 1. 292 return v
293 294 #----------------------------------------------------- 295 #
296 - def bot0(self, padz, ballpos, balldir):
297 """ npc AI (actually very dumb) """ 298 bpx,bpy,bpz=ballpos 299 v=0. 300 # bpx > 0. = dentro metacampo pad0 301 #if bpx > .35/self.BALLSPEED: 302 if bpx > .0: 303 if (abs(bpz-padz) > .08) and (abs(bpz) < .65): 304 v=1. if bpz > padz else -1. 305 else: v=self._centerpad(padz) 306 return v
307 308 #----------------------------------------------------- 309 #
310 - def bot1(self, padz, ballpos, balldir):
311 """ npc AI (less dumb) """ 312 bpx,bpy,bpz=ballpos 313 balldirz=balldir[2] 314 v=0. 315 if bpx > 0.: 316 d=.5/self.BALLSPEED 317 self.dbgprint("[CPU1]rot:%0.3f lim: %0.3f bpx:%0.3f"%(balldirz, d, bpx)) 318 if bpx < d: 319 self.dbgprint("...centering") 320 if abs(balldirz) > .003: return self._centerpad(padz) 321 if (abs(bpz-padz) > .08) and (abs(bpz) < .65): 322 v=1. if bpz > padz else -1. 323 self.dbgprint("...following") 324 else: v=self._centerpad(padz) 325 return v
326 327 #----------------------------------------------------- 328 #
329 - def npcloop(self, task):
330 pv=self.actualbot( 331 self.pad[0]['mdl'].getZ(), 332 self.ball.getPosition(), 333 self.ball.getImplicitVelocity() 334 ) 335 self.setpadvel(0, pv*self.PADVEL*self.CPUSPD*6.) 336 return task.again
337 338 #----------------------------------------------------- 339 #
340 - def _collphysetup(self):
341 self.parent.cTrav=CollisionTraverser() 342 self.parent.cTrav.setRespectPrevTransform(True) 343 self.parent.enableParticles() 344 self.collisionHandler = PhysicsCollisionHandler() 345 346 ballmodel=self.field.find("**/ball") 347 self.ballNP=self.field.attachNewNode(PandaNode("phball")) 348 ballAN=ActorNode("ballactnode") 349 ballANP=self.ballNP.attachNewNode(ballAN) 350 ballmodel.reparentTo(ballANP) 351 ballCollider = ballmodel.find("**/ball_collide") 352 self.collisionHandler.addCollider(ballCollider, ballANP) 353 self.parent.cTrav.addCollider(ballCollider, self.collisionHandler) 354 self.collisionHandler.addInPattern('ball-into-all') 355 self.accept('ball-into-all', self.collideEventIn) 356 self.parent.physicsMgr.attachPhysicalNode(ballAN) 357 # NOTE we'll drive the ball from the PhysicsObject 358 self.ball=self.ballNP.getChild(0).node().getPhysicsObject()
359 #!!! 360 ###self.ball.setOriented(True) 361 362 #----------------------------------------------------- 363 #
364 - def collideEventIn(self, entry):
365 intoNP=entry.getIntoNodePath() 366 vec=entry.getSurfaceNormal(intoNP) 367 #the ball hit a pad 368 if intoNP.getName().startswith("pad"): 369 #tweak the pad hit bounce speed 370 vec=vec*self.BALLSPEED*1.5 371 self.wallbouncheck(reset=True) 372 padi=int(intoNP.getName()[3]) 373 self.pad[padi]['totrly']+=1 374 self.playeffect('pad%d'%padi) 375 # ball's walls bounce 376 else: 377 wbc=self.wallbouncheck() 378 if wbc <> None: return self.playerscore(wbc) 379 else: vec=vec+self.ball.getVelocity() 380 self.playeffect('borderhit') 381 vec*=self.BALLSPEED 382 self.ballinpulse(vec=Vec3(vec.getX(), 0, vec.getZ()))
383 384 #----------------------------------------------------- 385 #
386 - def updatescore(self):
387 self.text['score'].setText('%0d %0d'%( 388 self.pad[1]['gam'], self.pad[0]['gam'] 389 ) 390 ) 391 self.text['sets'].setText('%s: %0d %s: %0d'%( 392 self.pad[1]['name'], self.pad[1]['set'], 393 self.pad[0]['name'], self.pad[0]['set'], 394 ) 395 )
396 397 #----------------------------------------------------- 398 # 399 foesdefeated=0 400 totsets=0
401 - def endset(self):
402 """ a set is won by one player """ 403 self.playeffect('applause_1') 404 405 won=self.pad[1]['gam'] > self.pad[0]['gam'] 406 self.dbgprint(">> END OF GAME - won by player %d"%won) 407 self.pad[0]['gam']=0 408 self.pad[1]['gam']=0 409 self.pad[won]['set']+=1 410 self.totsets+=1 411 412 # at each game the ball speed will increase (until BALLSPEEDMAX) 413 if self.BALLSPEED < self.BALLSPEEDMAX: self.BALLSPEED*=1.05 414 self.BALLSPEED = min(self.BALLSPEED, self.BALLSPEEDMAX) 415 self.dbgprint(">> BALLSPEED increased to %0.2f"%self.BALLSPEED) 416 417 # a set is won reaching the games limit self._SETTINGS['games'] but also exceeding the other score by 2 points, e.g.: 6-0 won but 6-5 keep going 418 if ( 419 self.pad[won]['set'] >= ((self._SETTINGS['sets']/2)+1) 420 and (abs(self.pad[0]['set'] - self.pad[1]['set'])) >= 2 421 ): 422 # if human wins and foe is' CPU, the game keep going increasing the cpu foe bravura and shortening the pad size, otherwise game over. 423 if ( 424 (self.pad[1]['set'] > self.pad[0]['set']) 425 and (self._SETTINGS['opponent'] == 'cpu') 426 ): 427 self.intermessage( 428 "%s defeated!\nHere come another"%self.pad[0]['name'], delay=3 429 ) 430 self.dbgprint(">>> %s defeated" % self.pad[0]['name']) 431 self.foesdefeated+=1 432 self.pad[0]['name']="CPU%d"%self.foesdefeated 433 self.pad[0]['set']=0 434 self.pad[1]['set']=0 435 if self.foesdefeated <= self._SETTINGS['maxfoes']: 436 self.PADVEL+=.5 437 self.actualbot=self._BOTS[self.foesdefeated] 438 for i in range(2): 439 # riduzione delle dim dei pad: a maxfoes viene ridotto di un 60% e la riduzione e' quindi proporzionale ai maxfoes ad ogni foe sconfitto 440 psz=self.pad[i]['mdl'].getSz() 441 dsz=60./self._SETTINGS['maxfoes'] 442 self.pad[i]['mdl'].setSz(psz-(psz*dsz/100)) 443 #recalc pad range 444 b=self.pad[1]['mdl'].getTightBounds() 445 w,n,h=b[1]-b[0] 446 self.PADLIMZ=.7-(h/2.) 447 self.ballreset() 448 else: self.gameover() 449 else: 450 self.ballreset() 451 self.intermessage("Set won by\n%s"%self.pad[won]['name'], delay=3) 452 self.updatescore()
453 454 #----------------------------------------------------- 455 #
456 - def intermessage(self, msg, scale=.1, delay=-1):
457 self.text['cmsg'].hide() 458 if msg and type(msg) == str: 459 self.text['cmsg'].setScale(scale) 460 self.text['cmsg'].setText(msg) 461 self.text['cmsg'].setPos(0,0) 462 self.text['cmsg'].show() 463 if delay > 0: 464 taskMgr.doMethodLater(delay, self.intermessage, 'gpl01_intmsg') 465 return None
466 467 #----------------------------------------------------- 468 #
469 - def gameover(self):
470 self.setmaintask(0) 471 self.ballNP.hide() 472 self.dbgprint("GAME OVER!") 473 seq=Sequence() 474 won=self.pad[1]['set'] > self.pad[0]['set'] 475 476 if self._SETTINGS['opponent'] == 'human': 477 wonmsg="Game won by\n'%s'"%self.pad[won]['name'] 478 seq.append(Func(self.intermessage, wonmsg)) 479 seq.append(Wait(3.0)) 480 value=self.pad[won]['set'] 481 else: 482 score=self.humanvscpuscore() 483 msg=[ 484 "Rallies %d x %d = %d"%( 485 self.pad[self._HUMANPAD]['totrly'], self._SCOREPOINTS['rallyunit'], 486 score['rallies'] 487 ), 488 "Bonus foes = %d"%score['bonus'], 489 "Penalty = %d"%score['penalty'], 490 "TOTAL SCORE = %d"%sum(score.values()) 491 ] 492 493 for i in range(1,len(msg)+1): 494 seq.append(Func(self.intermessage, "\n".join(msg[:i]))) 495 seq.append(Func(self.playeffect, 'ball_in')) 496 seq.append(Wait(1.5)) 497 498 value=sum(score.values()) 499 500 if callable(self.gameovercallback): 501 fu=Func(self.gameovercallback, 502 { 503 'opponent': self._SETTINGS['opponent'], 504 'winner': self.pad[won]['name'], 505 'value': str(value) 506 } 507 ) 508 else: fu=Wait(1) 509 510 seq.append(Wait(3.0)) 511 seq.append(Func(self.intermessage, 'GAME OVER', 0.3)) 512 seq.append(Wait(1.0)) 513 seq.append(fu) 514 515 seq.start()
516 517 #----------------------------------------------------- 518 #
519 - def humanvscpuscore(self):
520 sco={} 521 sco['rallies']=self.pad[self._HUMANPAD]['totrly'] * self._SCOREPOINTS['rallyunit'] 522 self.dbgprint("@@RLYsco:%r"%sco['rallies']) 523 524 sco['bonus']=self.foesdefeated * self._SCOREPOINTS['bonusunit'] 525 self.dbgprint("@@BONUS:%r"%sco['bonus']) 526 527 # penalty points will be assigned reaching the set limit to win 528 minsets=((self._SETTINGS['sets']/2)+1)*(self.foesdefeated+1) 529 sco['penalty']=-( 530 self.totsets - minsets 531 ) * self._SCOREPOINTS['penaltyunit'] 532 self.dbgprint("@@PENALTY:sets(%r) ~ foes(%r) ~ minsets(%r)=%r"%( 533 self.totsets, self.foesdefeated+1, minsets, sco['penalty'] 534 ) 535 ) 536 537 self.dbgprint("@@TOTAL SCORE:%r"%sum(sco.values())) 538 return sco
539 #----------------------------------------------------- 540 #
541 - def playerscore(self, player):
542 # 543 self.playeffect('ball_out') 544 self.setmaintask(0) 545 self.ball.setActive(False) 546 self.wallbouncheck(reset=True) 547 self.pad[player]['gam']+=1 548 self.playerturn=player 549 self.updatescore() 550 # a set is won reaching the games limit self._SETTINGS['games'] but also exceeding the other score by 2 points, e.g.: 6-0 won but 6-5 keep going 551 if ( 552 ( 553 self.pad[0]['gam'] >= self._SETTINGS['games'] 554 or self.pad[1]['gam'] >= self._SETTINGS['games'] 555 ) and abs(self.pad[0]['gam'] - self.pad[1]['gam']) >= 2 556 ): self.endset() 557 else: 558 self.checkmatchball() 559 self.ballreset()
560 561 #----------------------------------------------------- 562 #
563 - def checkmatchball(self):
564 # the player with set advantage 565 p0=0 if self.pad[0]['set'] >= self.pad[1]['set'] else 1 566 # the other player 567 p1=not p0 568 if ( 569 self.pad[p0]['set'] >= (self._SETTINGS['sets']/2) 570 ) and ( 571 (self.pad[p0]['set'] - self.pad[p1]['set']) >= 1 572 ) and ( 573 self.pad[p0]['gam'] >= (self._SETTINGS['games']-1) 574 ) and ( 575 (self.pad[p0]['gam'] - self.pad[p1]['gam']) >= 1 576 ): 577 self.dbgprint("@@ MATCH BALL FOR PLAYER\n%s!"%self.pad[p0]['name']) 578 self.intermessage( 579 "MATCH BALL FOR PLAYER\n%s!"%self.pad[p0]['name'], 580 delay=3 581 )
582 583 #----------------------------------------------------- 584 # 585 _bcc=[0,0]
586 - def wallbouncheck(self, reset=False):
587 """ check for triple bounces in a player's middlefield 588 """ 589 if reset: self._bcc=[0,0] 590 else: 591 # bi=1 if the ball hit @ pos <=0, 0 otherwise 592 bi=self.ball.getPosition()[0] <= 0 593 # increm pad side hits and 0 the opposite 594 self._bcc[bi]+=1 595 self._bcc[not bi]=0 596 if sum(self._bcc) > 2: return 1 if self._bcc[0] else 0 597 return None
598 599 #----------------------------------------------------- 600 #
601 - def ballinpulse(self, vec):
602 self.ball.setVelocity(0,0,0) 603 self.ball.addImpulse(vec)
604 605 #----------------------------------------------------- 606 #
607 - def ballreset(self, foo=None):
608 """ """ 609 b=self.pad[1]['mdl'].getTightBounds() 610 w,n,h=b[1]-b[0] 611 z=.67 612 self.PADLIMZ=z-(h/2.) 613 614 self.ballNP.hide() 615 self.ball.setActive(False) 616 self.ball.setVelocity(Vec3(0,0,0)) 617 self.ball.resetPosition(Point3(0,0,0)) 618 self._ballprepare() 619 self.ball.setActive(True) 620 self.ballNP.show() 621 self.setmaintask(1) 622 self.playeffect('ball_in')
623 624 #----------------------------------------------------- 625 #
626 - def ballrestart(self, foo=None):
627 """ to start the ball off the pad """ 628 self.ignore('space') 629 self._ballpreparego() 630 p=self.playerturn 631 # serve speed - randomply choosed 632 bs=random.uniform(self.BALLSPEED*1.0, self.BALLSPEED*2.0) 633 self.ballinpulse(Vec3([-bs, bs][p], 0, self.pad[p]['vel'])) 634 return None
635 636 #----------------------------------------------------- 637 #
638 - def _ballprepare(self):
639 p=self.playerturn 640 self.ballNP.wrtReparentTo(self.pad[p]['mdl']) 641 self.ballNP.setPos([-.08, .08][p], 0, 0) 642 if p == 0 and self._SETTINGS['opponent'] == "cpu": 643 taskMgr.doMethodLater(3, self.ballrestart, 'gpl01_npcbrstrt') 644 else: self.accept('space', self.ballrestart)
645
646 - def _ballpreparego(self):
647 x,y,z=self.ballNP.getPos(self.field) 648 self.ballNP.wrtReparentTo(self.field) 649 self.ballNP.setPos(Point3(0,0,0)) 650 self.ball.resetPosition(Point3(x,0,z))
651 652 #----------------------------------------------------- 653 #
654 - def setpadvel(self, p, v): self.pad[p]['vel']=v
655 656 #----------------------------------------------------- 657 # 658 _collshow=0
659 - def toggle_collisions(self):
660 self._collshow=not self._collshow 661 try: 662 l=self.parent.render.findAllMatches("**/+CollisionNode") 663 if self._collshow: 664 self.parent.cTrav.showCollisions(self.parent.render) 665 for cn in l: cn.show() 666 else: 667 self.parent.cTrav.hideCollisions() 668 for cn in l: cn.hide() 669 except: self.dbgprint("[cbsnipBase:toggle_collisions] no traverser")
670 671 #========================================================================= 672 # 673 if __name__ == "__main__": 674 """ Demo to show off how to use this class to run the pong game 675 press '1' for Human vs computer, '2' for Human vs human 676 press 'p' to pause the game 677 """ 678 loadPrcFileData("", """win-size 800 600 679 win-origin 0 0 680 model-path $MAIN_DIR/data/models/ 681 sync-video 0 682 #show-frame-rate-meter #t 683 """ 684 )
685 - class world(ShowBase):
686 - def __init__(self):
687 ShowBase.__init__(self) 688 self.game=None 689 self.accept('escape', sys.exit) 690 self.accept('p', self.pausegame) 691 self.accept('1', self.startgame) 692 self.accept('2', self.startgame2)
693
694 - def pausegame(self):
695 if self.game: self.game.pause()
696
697 - def stopgame(self):
698 if self.game: 699 self.game.finish() 700 del self.game 701 self.game=None
702
703 - def gocallback(self, score):
704 self.dbgprint(">> the scoreboard:\n'%r'"%score)
705
706 - def startgame(self):
707 self.stopgame() 708 if self.game == None: 709 self.game=gameplay( 710 self, settings={'opponent': 'cpu'}, callback=self.gocallback 711 )
712
713 - def startgame2(self):
714 self.stopgame() 715 if self.game == None: 716 self.game=gameplay( 717 self, settings={'opponent': 'human'}, callback=self.gocallback 718 )
719 720 W=world() 721 run() 722