Do you play games on GAMEE? It’s a free gaming network which offers real money prizes.
I do not play for money at GAMEE, but I like its hyper causal games, and Color Hit is one of them.
It’s a game similar to Knife Hit, which has already been explained in a tutorial series, but rather than simply throwing knives at a target, Color Hit introduces colored sectors and knives.
Obviously, you can only hit target sectors which match with the color of the knife you are throwing, or it’s game over.
Have a try:
Click or tap to throw a knife. Match knife color with target color or it’s game over. Also, do not throw knives over other knives.
Easy and fun, and here is the completely commented source code:
// the game itself let game; // global game options let gameOptions = { // target radius, in pixels targetRadius: 200, // array with all target colors targetColors: [0xff0000, 0x00ff00, 0x0000ff], // target Y position, in screen height ratio targetY: 1 / 4, // target rotation speed, in degrees per frame rotationSpeed: 3, // knife throwing duration, in milliseconds throwSpeed: 150, // minimum angle between two knives minAngle: 15, // max rotation speed variation, in degrees per frame rotationVariation: 2, // interval before next rotation speed variation, in milliseconds changeTime: 2000, // maximum rotation speed, in degrees per frame maxRotationSpeed: 6 } // once the window loads... window.onload = function() { let gameConfig = { type: Phaser.AUTO, backgroundColor: 0xeeeeee, scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH, parent: "thegame", width: 750, height: 1334 }, scene: playGame } game = new Phaser.Game(gameConfig); window.focus(); } // PlayGame scene class playGame extends Phaser.Scene { // constructor constructor() { super("PlayGame"); } // method to be executed when the scene preloads preload() { // load the knife this.load.image("knife", "knife.png"); } // method to be executed once the scene has been created create() { // make a graphic object but don'y add it to the game let graphics = this.make.graphics({ x: 0, y: 0, add: false }); // angle covered by a slice this.sliceAngle = 2 * Math.PI / gameOptions.targetColors.length; // loop through all colors for(let i = 0; i < gameOptions.targetColors.length; i ++) { // set fill stile graphics.fillStyle(gameOptions.targetColors[i], 1); // draw a target slice graphics.slice(gameOptions.targetRadius, gameOptions.targetRadius, gameOptions.targetRadius, 2 * Math.PI - this.sliceAngle * i, 2 * Math.PI - this.sliceAngle * (i + 1), true); // close and fill the path graphics.fillPath(); } // generate wheel texture from the graphics graphics.generateTexture("wheel", gameOptions.targetRadius * 2, gameOptions.targetRadius * 2); // at the beginning of the game, both current rotation speed and new rotation speed are set to default rotation speed this.currentRotationSpeed = gameOptions.rotationSpeed; this.newRotationSpeed = gameOptions.rotationSpeed; // can the player throw a knife? Yes, at the beginning of the game this.canThrow = true; // group to store all rotating knives this.knifeGroup = this.add.group(); // add the knife this.knife = this.add.sprite(game.config.width / 2, game.config.height / 5 * 4, "knife"); // random color of the target to hit this.knife.target = Phaser.Math.Between(0, gameOptions.targetColors.length - 1); // tint the knife accordingly this.knife.tint = gameOptions.targetColors[this.knife.target]; // add the target this.target = this.add.sprite(game.config.width / 2, game.config.height * gameOptions.targetY, "wheel"); // move the target to front this.target.depth = 1; // wait for player input to throw a knife this.input.on("pointerdown", this.throwKnife, this); // this is how we create a looped timer event let timedEvent = this.time.addEvent({ // delay, in milliseconds delay: gameOptions.changeTime, // callback function callback: this.changeSpeed, // callback scope callbackScope: this, // the event will repeat endlessly loop: true }); } // method to change the rotation speed of the target changeSpeed() { // random number between -gameOptions.rotationVariation and gameOptions.rotationVariation let variation = Phaser.Math.FloatBetween(-gameOptions.rotationVariation, gameOptions.rotationVariation); // new rotation speed this.newRotationSpeed = (this.currentRotationSpeed + variation) * Phaser.Math.RND.sign(); // set new rotation speed limits this.newRotationSpeed = Phaser.Math.Clamp(this.newRotationSpeed, -gameOptions.maxRotationSpeed, gameOptions.maxRotationSpeed); } // method to throw a knife throwKnife() { // can the player throw? if(this.canThrow) { // player can't throw anymore this.canThrow = false; // tween to throw the knife this.tweens.add({ // add the knife to tween targets targets: [this.knife], // y destination y: this.target.y + this.target.width / 2, // tween duration duration: gameOptions.throwSpeed, // callback scope callbackScope: this, // function to be executed once the tween has been completed onComplete: function(tween) { // at the moment, this is a legal hit let legalHit = true; // if the knife hit the wrong color... if(Math.floor(Phaser.Math.Angle.Normalize(this.target.rotation - Math.PI / 2) / this.sliceAngle) != this.knife.target) { // ... not a legal hit legalHit = false; } // if still a legal hit... else { // get an array with all rotating knives let children = this.knifeGroup.getChildren(); // loop through rotating knives for (let i = 0; i < children.length; i ++) { // is the knife too close to the i-th knife? if(Math.abs(Phaser.Math.Angle.ShortestBetween(this.target.angle, children[i].impactAngle)) < gameOptions.minAngle) { // this is not a legal hit legalHit = false; // no need to continue with the loop break; } } } // is this a legal hit? if(legalHit) { // player can now throw again this.canThrow = true; // addi the rotating knife in the same place of the knife just landed on target let knife = this.add.sprite(this.knife.x, this.knife.y, "knife"); // impactAngle property saves the target angle when the knife hits the target knife.impactAngle = this.target.angle; knife.tint = gameOptions.targetColors[this.knife.target]; // add the rotating knife to knifeGroup group this.knifeGroup.add(knife); // bring back the knife to its starting position this.knife.y = game.config.height / 5 * 4; // set a new random color target this.knife.target = Phaser.Math.Between(0, gameOptions.targetColors.length - 1); // tint the knife accordingly this.knife.tint = gameOptions.targetColors[this.knife.target]; } // in case this is not a legal hit else{ // tween to make the knife fall down this.tweens.add({ // add the knife to tween targets targets: [this.knife], // y destination y: game.config.height + this.knife.height, // rotation destination, in radians rotation: 5, // tween duration duration: gameOptions.throwSpeed * 4, // callback scope callbackScope: this, // function to be executed once the tween has been completed onComplete: function(tween) { // restart the game this.scene.start("PlayGame") } }); } } }); } } // method to be executed at each frame. Please notice the arguments. update(time, delta) { // rotate the target this.target.angle += this.currentRotationSpeed; // get an array with all rotating knives let children = this.knifeGroup.getChildren(); // loop through rotating knives for (let i = 0; i < children.length; i ++) { // rotate the knife children[i].angle += this.currentRotationSpeed; // turn knife angle in radians let radians = Phaser.Math.DegToRad(children[i].angle + 90); // trigonometry to make the knife rotate around target center children[i].x = this.target.x + (this.target.width / 2) * Math.cos(radians); children[i].y = this.target.y + (this.target.width / 2) * Math.sin(radians); } // adjust current rotation speed using linear interpolation this.currentRotationSpeed = Phaser.Math.Linear(this.currentRotationSpeed, this.newRotationSpeed, delta / 1000); } }
I found it more fun than Knife Hit because of the different colors, maybe we could randomize a bit more sector colors, in a further step, meanwhile download the source code.