| OLD | NEW |
| (Empty) |
| 1 part of game; | |
| 2 | |
| 3 const double _steeringThreshold = 0.0; | |
| 4 const double _steeringMax = 150.0; | |
| 5 | |
| 6 // Random generator | |
| 7 Math.Random _rand = new Math.Random(); | |
| 8 | |
| 9 const double _gameSizeWidth = 1024.0; | |
| 10 const double _gameSizeHeight = 1024.0; | |
| 11 | |
| 12 const double _shipRadius = 30.0; | |
| 13 const double _lrgAsteroidRadius = 40.0; | |
| 14 const double _medAsteroidRadius = 20.0; | |
| 15 const double _smlAsteroidRadius = 10.0; | |
| 16 const double _maxAsteroidSpeed = 1.0; | |
| 17 | |
| 18 const int _lifeTimeLaser = 50; | |
| 19 | |
| 20 const int _numStarsInStarField = 150; | |
| 21 | |
| 22 class GameDemoWorld extends NodeWithSize { | |
| 23 | |
| 24 // Images | |
| 25 Image _imgNebula; | |
| 26 | |
| 27 SpriteSheet _spriteSheet; | |
| 28 | |
| 29 // Inputs | |
| 30 double _joystickX = 0.0; | |
| 31 double _joystickY = 0.0; | |
| 32 bool _fire; | |
| 33 | |
| 34 Node _gameLayer; | |
| 35 | |
| 36 Ship _ship; | |
| 37 List<Asteroid> _asteroids = []; | |
| 38 List<Laser> _lasers = []; | |
| 39 StarField _starField; | |
| 40 Nebula _nebula; | |
| 41 | |
| 42 GameDemoWorld(ImageMap images, this._spriteSheet) : super(new Size(_gameSizeWi
dth, _gameSizeHeight)) { | |
| 43 | |
| 44 // Fetch images | |
| 45 _imgNebula = images["res/nebula.png"]; | |
| 46 | |
| 47 _gameLayer = new Node(); | |
| 48 this.addChild(_gameLayer); | |
| 49 | |
| 50 // Add some asteroids to the game world | |
| 51 for (int i = 0; i < 5; i++) { | |
| 52 addAsteroid(AsteroidSize.large); | |
| 53 } | |
| 54 for (int i = 0; i < 5; i++) { | |
| 55 addAsteroid(AsteroidSize.medium); | |
| 56 } | |
| 57 | |
| 58 // Add ship | |
| 59 addShip(); | |
| 60 | |
| 61 // Add starfield | |
| 62 _starField = new StarField(_spriteSheet["star.png"], _numStarsInStarField); | |
| 63 _starField.zPosition = -2.0; | |
| 64 addChild(_starField); | |
| 65 | |
| 66 // Add nebula | |
| 67 addNebula(); | |
| 68 | |
| 69 userInteractionEnabled = true; | |
| 70 handleMultiplePointers = true; | |
| 71 } | |
| 72 | |
| 73 // Methods for adding game objects | |
| 74 | |
| 75 void addAsteroid(AsteroidSize size, [Point pos]) { | |
| 76 Asteroid asteroid = new Asteroid(_spriteSheet["asteroid_big_1.png"], size); | |
| 77 asteroid.zPosition = 1.0; | |
| 78 if (pos != null) asteroid.position = pos; | |
| 79 _gameLayer.addChild(asteroid); | |
| 80 _asteroids.add(asteroid); | |
| 81 } | |
| 82 | |
| 83 void addShip() { | |
| 84 Ship ship = new Ship(_spriteSheet["ship.png"]); | |
| 85 ship.zPosition = 10.0; | |
| 86 _gameLayer.addChild(ship); | |
| 87 _ship = ship; | |
| 88 } | |
| 89 | |
| 90 void addLaser() { | |
| 91 Laser laser = new Laser(_spriteSheet["laser.png"], _ship); | |
| 92 laser.zPosition = 8.0; | |
| 93 _lasers.add(laser); | |
| 94 _gameLayer.addChild(laser); | |
| 95 } | |
| 96 | |
| 97 void addNebula() { | |
| 98 _nebula = new Nebula.withImage(_imgNebula); | |
| 99 _gameLayer.addChild(_nebula); | |
| 100 } | |
| 101 | |
| 102 void update(double dt) { | |
| 103 // Move asteroids | |
| 104 for (Asteroid asteroid in _asteroids) { | |
| 105 asteroid.position = pointAdd(asteroid.position, asteroid._movementVector); | |
| 106 } | |
| 107 | |
| 108 // Move lasers and remove expired lasers | |
| 109 for (int i = _lasers.length - 1; i >= 0; i--) { | |
| 110 Laser laser = _lasers[i]; | |
| 111 laser.move(); | |
| 112 if (laser._frameCount > _lifeTimeLaser) { | |
| 113 laser.removeFromParent(); | |
| 114 _lasers.removeAt(i); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // Apply thrust to ship | |
| 119 if (_joystickX != 0.0 || _joystickY != 0.0) { | |
| 120 _ship.thrust(_joystickX, _joystickY); | |
| 121 } | |
| 122 | |
| 123 // Move ship | |
| 124 _ship.move(); | |
| 125 | |
| 126 // Check collisions between asteroids and lasers | |
| 127 for (int i = _lasers.length -1; i >= 0; i--) { | |
| 128 // Iterate over all the lasers | |
| 129 Laser laser = _lasers[i]; | |
| 130 | |
| 131 for (int j = _asteroids.length - 1; j >= 0; j--) { | |
| 132 // Iterate over all the asteroids | |
| 133 Asteroid asteroid = _asteroids[j]; | |
| 134 | |
| 135 // Check for collision | |
| 136 if (pointQuickDist(laser.position, asteroid.position) < laser.radius + a
steroid.radius) { | |
| 137 // Remove laser | |
| 138 laser.removeFromParent(); | |
| 139 _lasers.removeAt(i); | |
| 140 | |
| 141 // Add asteroids | |
| 142 if (asteroid._asteroidSize == AsteroidSize.large) { | |
| 143 for (int a = 0; a < 3; a++) addAsteroid(AsteroidSize.medium, asteroi
d.position); | |
| 144 } | |
| 145 else if (asteroid._asteroidSize == AsteroidSize.medium) { | |
| 146 for (int a = 0; a < 5; a++) addAsteroid(AsteroidSize.small, asteroid
.position); | |
| 147 } | |
| 148 | |
| 149 // Remove asteroid | |
| 150 asteroid.removeFromParent(); | |
| 151 _asteroids.removeAt(j); | |
| 152 break; | |
| 153 } | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // Move objects to center camera and warp objects around the edges | |
| 158 centerCamera(); | |
| 159 warpObjects(); | |
| 160 } | |
| 161 | |
| 162 void centerCamera() { | |
| 163 const cameraDampening = 0.1; | |
| 164 Point delta = new Point(_gameSizeWidth/2 - _ship.position.x, _gameSizeHeight
/2 - _ship.position.y); | |
| 165 delta = pointMult(delta, cameraDampening); | |
| 166 | |
| 167 for (Node child in _gameLayer.children) { | |
| 168 child.position = pointAdd(child.position, delta); | |
| 169 } | |
| 170 | |
| 171 // Update starfield | |
| 172 _starField.move(delta.x, delta.y); | |
| 173 } | |
| 174 | |
| 175 void warpObjects() { | |
| 176 for (Node child in _gameLayer.children) { | |
| 177 if (child.position.x < 0) child.position = pointAdd(child.position, new Po
int(_gameSizeWidth, 0.0)); | |
| 178 if (child.position.x >= _gameSizeWidth) child.position = pointAdd(child.po
sition, new Point(-_gameSizeWidth, 0.0)); | |
| 179 if (child.position.y < 0) child.position = pointAdd(child.position, new Po
int(0.0, _gameSizeHeight)); | |
| 180 if (child.position.y >= _gameSizeHeight) child.position = pointAdd(child.p
osition, new Point(0.0, -_gameSizeHeight)); | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 // Handling controls | |
| 185 | |
| 186 void controlSteering(double x, double y) { | |
| 187 _joystickX = x; | |
| 188 _joystickY = y; | |
| 189 } | |
| 190 | |
| 191 void controlFire() { | |
| 192 addLaser(); | |
| 193 } | |
| 194 | |
| 195 // Handle pointer events | |
| 196 | |
| 197 int _firstPointer = -1; | |
| 198 int _secondPointer = -1; | |
| 199 Point _firstPointerDownPos; | |
| 200 | |
| 201 bool handleEvent(SpriteBoxEvent event) { | |
| 202 Point pointerPos = convertPointToNodeSpace(event.boxPosition); | |
| 203 int pointer = event.pointer; | |
| 204 | |
| 205 switch (event.type) { | |
| 206 case 'pointerdown': | |
| 207 if (_firstPointer == -1) { | |
| 208 // Assign the first pointer | |
| 209 _firstPointer = pointer; | |
| 210 _firstPointerDownPos = pointerPos; | |
| 211 } | |
| 212 else if (_secondPointer == -1) { | |
| 213 // Assign second pointer | |
| 214 _secondPointer = pointer; | |
| 215 controlFire(); | |
| 216 } | |
| 217 else { | |
| 218 // There is a pointer used for steering, let's fire instead | |
| 219 controlFire(); | |
| 220 } | |
| 221 break; | |
| 222 case 'pointermove': | |
| 223 if (pointer == _firstPointer) { | |
| 224 // Handle turning control | |
| 225 double joystickX = 0.0; | |
| 226 double deltaX = pointerPos.x - _firstPointerDownPos.x; | |
| 227 if (deltaX > _steeringThreshold || deltaX < -_steeringThreshold) { | |
| 228 joystickX = (deltaX - _steeringThreshold)/(_steeringMax - _steeringT
hreshold); | |
| 229 if (joystickX > 1.0) joystickX = 1.0; | |
| 230 if (joystickX < -1.0) joystickX = -1.0; | |
| 231 } | |
| 232 | |
| 233 double joystickY = 0.0; | |
| 234 double deltaY = pointerPos.y - _firstPointerDownPos.y; | |
| 235 if (deltaY > _steeringThreshold || deltaY < -_steeringThreshold) { | |
| 236 joystickY = (deltaY - _steeringThreshold)/(_steeringMax - _steeringT
hreshold); | |
| 237 if (joystickY > 1.0) joystickY = 1.0; | |
| 238 if (joystickY < -1.0) joystickY = -1.0; | |
| 239 } | |
| 240 | |
| 241 controlSteering(joystickX, joystickY); | |
| 242 } | |
| 243 break; | |
| 244 case 'pointerup': | |
| 245 case 'pointercancel': | |
| 246 if (pointer == _firstPointer) { | |
| 247 // Un-assign the first pointer | |
| 248 _firstPointer = -1; | |
| 249 _firstPointerDownPos = null; | |
| 250 controlSteering(0.0, 0.0); | |
| 251 } | |
| 252 else if (pointer == _secondPointer) { | |
| 253 _secondPointer = -1; | |
| 254 } | |
| 255 break; | |
| 256 default: | |
| 257 break; | |
| 258 } | |
| 259 return true; | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 // Game objects | |
| 264 | |
| 265 enum AsteroidSize { | |
| 266 small, | |
| 267 medium, | |
| 268 large, | |
| 269 } | |
| 270 | |
| 271 class Asteroid extends Sprite { | |
| 272 Point _movementVector; | |
| 273 AsteroidSize _asteroidSize; | |
| 274 double _radius; | |
| 275 | |
| 276 double get radius { | |
| 277 if (_radius != null) return _radius; | |
| 278 if (_asteroidSize == AsteroidSize.small) _radius = _smlAsteroidRadius; | |
| 279 else if (_asteroidSize == AsteroidSize.medium) _radius = _medAsteroidRadius; | |
| 280 else if (_asteroidSize == AsteroidSize.large) _radius = _lrgAsteroidRadius; | |
| 281 return _radius; | |
| 282 } | |
| 283 | |
| 284 Asteroid(Texture img, AsteroidSize this._asteroidSize) : super(img) { | |
| 285 size = new Size(radius * 2.0, radius * 2.0); | |
| 286 position = new Point(_gameSizeWidth * _rand.nextDouble(), _gameSizeHeight *
_rand.nextDouble()); | |
| 287 rotation = 360.0 * _rand.nextDouble(); | |
| 288 | |
| 289 _movementVector = new Point(_rand.nextDouble() * _maxAsteroidSpeed * 2 - _ma
xAsteroidSpeed, | |
| 290 _rand.nextDouble() * _maxAsteroidSpeed * 2 - _ma
xAsteroidSpeed); | |
| 291 | |
| 292 userInteractionEnabled = true; | |
| 293 } | |
| 294 | |
| 295 bool handleEvent(SpriteBoxEvent event) { | |
| 296 if (event.type == "pointerdown") { | |
| 297 colorOverlay = new Color(0x99ff0000); | |
| 298 } | |
| 299 else if (event.type == "pointerup") { | |
| 300 colorOverlay = null; | |
| 301 } | |
| 302 return false; | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 class Ship extends Sprite { | |
| 307 Vector2 _movementVector; | |
| 308 double _rotationTarget; | |
| 309 | |
| 310 Ship(Texture img) : super(img) { | |
| 311 _movementVector = new Vector2.zero(); | |
| 312 rotation = _rotationTarget = 270.0; | |
| 313 | |
| 314 // Create sprite | |
| 315 size = new Size(_shipRadius * 2.0, _shipRadius * 2.0); | |
| 316 position = new Point(_gameSizeWidth/2.0, _gameSizeHeight/2.0); | |
| 317 } | |
| 318 | |
| 319 void thrust(double x, double y) { | |
| 320 _rotationTarget = convertRadians2Degrees(Math.atan2(y, x)); | |
| 321 Vector2 directionVector = new Vector2(x, y).normalize(); | |
| 322 _movementVector.addScaled(directionVector, 1.0); | |
| 323 } | |
| 324 | |
| 325 void move() { | |
| 326 position = new Point(position.x + _movementVector[0], position.y + _movement
Vector[1]); | |
| 327 _movementVector.scale(0.9); | |
| 328 | |
| 329 rotation = dampenRotation(rotation, _rotationTarget, 0.1); | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 class Laser extends Sprite { | |
| 334 int _frameCount = 0; | |
| 335 Point _movementVector; | |
| 336 double radius = 10.0; | |
| 337 | |
| 338 Laser(Texture img, Ship ship) : super(img) { | |
| 339 size = new Size(20.0, 20.0); | |
| 340 position = ship.position; | |
| 341 rotation = ship.rotation + 90.0; | |
| 342 transferMode = TransferMode.plus; | |
| 343 double rotRadians = convertDegrees2Radians(rotation); | |
| 344 _movementVector = pointMult(new Point(Math.sin(rotRadians), -Math.cos(rotRad
ians)), 10.0); | |
| 345 _movementVector = new Point(_movementVector.x + ship._movementVector[0], _mo
vementVector.y + ship._movementVector[1]); | |
| 346 } | |
| 347 | |
| 348 void move() { | |
| 349 position = pointAdd(position, _movementVector); | |
| 350 _frameCount++; | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 // Background starfield | |
| 355 | |
| 356 class StarField extends Node { | |
| 357 Texture _img; | |
| 358 int _numStars; | |
| 359 List<Point> _starPositions; | |
| 360 List<double> _starScales; | |
| 361 List<double> _opacity; | |
| 362 | |
| 363 StarField(this._img, this._numStars) { | |
| 364 _starPositions = []; | |
| 365 _starScales = []; | |
| 366 _opacity = []; | |
| 367 | |
| 368 for (int i = 0; i < _numStars; i++) { | |
| 369 _starPositions.add(new Point(_rand.nextDouble() * _gameSizeWidth, _rand.ne
xtDouble() * _gameSizeHeight)); | |
| 370 _starScales.add(_rand.nextDouble()); | |
| 371 _opacity.add(_rand.nextDouble() * 0.5 + 0.5); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void paint(RenderCanvas canvas) { | |
| 376 // Setup paint object for opacity and transfer mode | |
| 377 Paint paint = new Paint(); | |
| 378 paint.setTransferMode(TransferMode.plus); | |
| 379 | |
| 380 double baseScaleX = 32.0 / _img.size.width; | |
| 381 double baseScaleY = 32.0 / _img.size.height; | |
| 382 | |
| 383 // Draw each star | |
| 384 for (int i = 0; i < _numStars; i++) { | |
| 385 Point pos = _starPositions[i]; | |
| 386 double scale = _starScales[i]; | |
| 387 paint.color = new Color.fromARGB((255.0*_opacity[i]).toInt(), 255, 255, 25
5); | |
| 388 | |
| 389 canvas.save(); | |
| 390 | |
| 391 canvas.translate(pos.x, pos.y); | |
| 392 canvas.scale(baseScaleX * scale, baseScaleY * scale); | |
| 393 | |
| 394 canvas.drawImageRect(_img.image, _img.frame, _img.spriteSourceSize, paint)
; | |
| 395 | |
| 396 canvas.restore(); | |
| 397 } | |
| 398 } | |
| 399 | |
| 400 void move(double dx, double dy) { | |
| 401 for (int i = 0; i < _numStars; i++) { | |
| 402 double xPos = _starPositions[i].x; | |
| 403 double yPos = _starPositions[i].y; | |
| 404 double scale = _starScales[i]; | |
| 405 | |
| 406 xPos += dx * scale; | |
| 407 yPos += dy * scale; | |
| 408 | |
| 409 if (xPos >= _gameSizeWidth) xPos -= _gameSizeWidth; | |
| 410 if (xPos < 0) xPos += _gameSizeWidth; | |
| 411 if (yPos >= _gameSizeHeight) yPos -= _gameSizeHeight; | |
| 412 if (yPos < 0) yPos += _gameSizeHeight; | |
| 413 | |
| 414 _starPositions[i] = new Point(xPos, yPos); | |
| 415 } | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 class Nebula extends Node { | |
| 420 | |
| 421 Nebula.withImage(Image img) { | |
| 422 for (int i = 0; i < 2; i++) { | |
| 423 for (int j = 0; j < 2; j++) { | |
| 424 Sprite sprt = new Sprite.fromImage(img); | |
| 425 sprt.pivot = Point.origin; | |
| 426 sprt.position = new Point(i * _gameSizeWidth - _gameSizeWidth, j * _game
SizeHeight - _gameSizeHeight); | |
| 427 addChild(sprt); | |
| 428 } | |
| 429 } | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 // Convenience methods | |
| 434 | |
| 435 Point pointAdd(Point a, Point b) { | |
| 436 return new Point(a.x+ b.x, a.y + b.y); | |
| 437 } | |
| 438 | |
| 439 Point pointMult(Point a, double multiplier) { | |
| 440 return new Point(a.x * multiplier, a.y * multiplier); | |
| 441 } | |
| 442 | |
| 443 double dampenRotation(double src, double dst, double dampening) { | |
| 444 double delta = dst - src; | |
| 445 while (delta > 180.0) delta -= 360; | |
| 446 while (delta < -180) delta += 360; | |
| 447 delta *= dampening; | |
| 448 | |
| 449 return src + delta; | |
| 450 } | |
| 451 | |
| 452 double pointQuickDist(Point a, Point b) { | |
| 453 double dx = a.x - b.x; | |
| 454 double dy = a.y - b.y; | |
| 455 if (dx < 0.0) dx = -dx; | |
| 456 if (dy < 0.0) dy = -dy; | |
| 457 if (dx > dy) { | |
| 458 return dx + dy/2.0; | |
| 459 } | |
| 460 else { | |
| 461 return dy + dx/2.0; | |
| 462 } | |
| 463 } | |
| OLD | NEW |