vmars316 Posted April 20, 2016 Share Posted April 20, 2016 Hello & Thanks , I am working on a javescript(only) game . I have the shooter(thrower) setup and moving via arrowKeys . And have initial setup for bullet(cowpie) . But I need help(example) setting cowpie up so that I can have multiple cowpies in play . var Cowpie = function () { var self = this; this.idTag = 'cowpie'; this.x = thrower.x; this.y = thrower.y; this.width= 64; this.height = 64; this.speedX = 0; this.speedY = 5; this.visible = true; this.directionY = -1; this.moveMe = false ; this.update = function() { self.y = self.y+ (self.speedY * self.directionY); // always -1 } self.moveMe = false ; } } // cowpie = new Cowpie(); cowpie.idTag ; // = 'cowpie'; cowpie.x ; // = 0; cowpie.y ; // = thrower.y; cowpie.width ; // = 64; cowpie.height ; // = 64; cowpie.speedX ; // = 0; cowpie.speedY ; // = -5; cowpie.visible ; // = true ; cowpie.directionY ; // = -1; cowpie.moveMe ; // = true ; . The running game is here: http://liesandcowpies.com/javascript/BenghaziGame-starter-05-Thrower-Cowpie.html The code shown below: <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta charset="utf-8" /> <title>move pieThrower</title> <!-- file:///C:/javascript-Pure/otherObj/BenghaziGame-starter-05-Thrower-Cowpie.html --> <!-- http://liesandcowpies.com/javascript/ --> <style> canvas { border:1px solid #d3d3d3; background-color: #f1f1f1; } #assets { visibility: hidden; } </style> </head> <body onload="startGame()"> fromWhere= <span id="fromWhere">fromWhere</span><br> idTag= <span id="idTag">idTag</span><br> this.idTag= <span id="thisIdTag">this.idTag</span><br> this.visible= <span id="this.visible"> this.visible</span><br> this.tripsMax= <span id="this.tripsMax"> this.tripsMax</span><br> this.tripsCnt= <span id="this.tripsCnt"> this.tripsCnt</span><br> this.directionX= <span id="this.directionX"> this.directionX</span><br> this.x= <span id="this.x"> this.x</span><br> thrower x,y,w,h= <span id="thrower.xywh">thrower.x,y,w,h</span><br> <div align="center"> <table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="width:70%";><p id="traceMsg">traceLog goes here:</p> </td> <td style="width:30%";> <canvas id="canvas" width="300" height="300"></canvas> </td> </tr> </tbody> </table> </div> <div id="assets"> <img id="truth01" src="sprites/truth01.png" width="64" height="64" /> <img id="truth02" src="sprites/truth02.png" width="64" height="64" /> <img id="lies01" src="sprites/lies01.png" width="64" height="64" /> <img id="lies02" src="sprites/lies02.png" width="64" height="64" /> <img id="cowpie" src="sprites/cowpie.png" width="32" height="32" /> <img id="thrower" src="sprites/thrower.png" width="64" height="64" /> <audio id="closeDoor" src="sounds/CloseDoor.ogg"></audio> </div> <script type='text/javascript'> // var oneTraceLine = ""; var traceYESorNO = false; var updateFor1stTime = 0; var fromWhere = "fromWhere"; var timesInTripsCk=0; var visible = true; var thisx=0; var tripsMax=0; priorTripsMax = 0; var thisIdTag; var holdThrower_x = 0; var idTag = "truth01"; var idTagTh = "thrower"; var tripsCnt=0; var directionX=1 ; var addit = 0; // canvas = document.getElementById("canvas"); // get the canvas ctx = canvas.getContext('2d'); // create canvas Context; var targetImgsCnt = 0; var idTag = "truth01"; var totalTrips = 0; var targetImgs = [document.getElementById("truth01"), document.getElementById("lies01"), //, document.getElementById("truth02"), document.getElementById("lies02"), document.getElementById("thrower"), document.getElementById("cowpie") ] ; // // function startGame() { var Cowpie = function () { var self = this; this.idTag = 'cowpie'; this.x = thrower.x; this.y = thrower.y; this.width= 64; this.height = 64; this.speedX = 0; this.speedY = 5; this.visible = true; this.directionY = -1; this.moveMe = false ; this.update = function() { self.y = self.y+ (self.speedY * self.directionY); // always -1 } self.moveMe = false ; } } // cowpie = new Cowpie(); cowpie.idTag ; // = 'cowpie'; cowpie.x ; // = 0; cowpie.y ; // = thrower.y; cowpie.width ; // = 64; cowpie.height ; // = 64; cowpie.speedX ; // = 0; cowpie.speedY ; // = -5; cowpie.visible ; // = true ; cowpie.directionY ; // = -1; cowpie.moveMe ; // = true ; // var Thrower = function () { var self = this; this.idTag = 'thrower'; this.x = (canvas.width / 2); this.y = canvas.height - 64; this.width= 64; this.height = 64; this.speedX = 1; this.speedY = 0; this.visible = true; this.directionX = 5; this.moveMe = false ; this.update = function() { self.x = self.x + (self.speedX * self.directionX); // always either +1 or -1 } self.moveMe = false ; } } // thrower = new Thrower(); thrower.idTag ; // = 'thrower'; thrower.x ; // = 0; thrower.y ; // = canvas.height - 64; thrower.width ; // = 64; thrower.height ; // = 64; thrower.speedX ; // = 1; thrower.speedY ; // = 0; thrower.visible ; // = true ; thrower.directionX ; // = 1; thrower.moveMe ; // = true ; // myGameArea.start(); } // function updateGameArea() { myGameArea.clear(); targetImgsCnt = 4; if(thrower.visible) { if(thrower.moveMe) {thrower.update();} ctx.drawImage(targetImgs[targetImgsCnt], thrower.x, thrower.y, thrower.width, thrower.height); /*120*/ document.getElementById("thrower.xywh").innerHTML = thrower.x; } } // var myGameArea = { start : function() { thrower.moveMe = false ; interval = setInterval(updateGameArea, 5); // updateGameArea(); }, clear : function() { ctx.clearRect(0, 0, canvas.width, canvas.height); }, stop : function() { clearInterval(this.interval); } } // document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keyup", keyUpHandler, false); document.addEventListener("mousemove", mouseMoveHandler, false); function keyDownHandler(e) { if(e.keyCode == 39 || event.keyCode == 68) { // rightPressed = true; // alert("keyDownHandler: rightPressed"); thrower.directionX = 7; thrower.moveMe = true; } else if(e.keyCode == 37 || event.keyCode == 65) { // leftPressed = true; // alert("keyDownHandler: leftPressed"); thrower.directionX = -7; thrower.moveMe = true; } } function keyUpHandler(e) { if(e.keyCode == 38 || event.keyCode == 87) { rightPressed = false; } else if(e.keyCode == 40 || event.keyCode == 83) { leftPressed = false; } } function mouseMoveHandler(e) { var relativeX = e.clientX - canvas.offsetLeft; // alert("function mouseMoveHandler(e)"); } // // file:///C:/javascript-Pure/otherObj/ // </script> </body> </html> Thanks Quote Link to comment Share on other sites More sharing options...
permith Posted April 20, 2016 Share Posted April 20, 2016 You're looking for Arrays. Basically it's a variable that holds multiple variables, and provides functionality to add/remove/access each one individually. Quote Link to comment Share on other sites More sharing options...
vmars316 Posted April 20, 2016 Author Share Posted April 20, 2016 Thanks , but what I need is an example of how to set up the Object definitions , object , constructor , prototype , etc.. I only know how to set up Object & new object . Quote Link to comment Share on other sites More sharing options...
mattstyles Posted April 21, 2016 Share Posted April 21, 2016 Looks like your simplest solution is to use a factory function to create new objects for you. A pattern you can use: var Bullet = function( x, y ) { this.name = 'bullet' this.x = x this.y = y } Bullet.prototype.update = function( dt ) { this.x += dt this.y += dt } This creates a constructor function and appends an update method to the prototype. JS is prototypal and not classical, although from the end point-of-view if you are using JS like this there isn’t a huge amount of operational difference (loads and loads of difference underneath). The new `class` syntax basically works out to this, although browsers might implement things differently underneath (things like Babel, which transpile `class` back to ES3 standard do it like this). A constructor function, when invoked with `new`, creates an object with a prototype. It'll inherit from the raw `object` and also have any of your prototype methods that you have added also. Methods will be invoked with the context of this object, unless the scope is mutated by something else. In the `Bullet` example above, both `x` and `y` are available via `this` from a newly instantiated `Bullet` instance. To do that instantiation: var bullet = new Bullet( 100, 100 ) `bullet` is an instance of `Bullet`. The capitalisation is a convention, JS doesn't care, but note that crucially variables are case-sensitive in JS. Up to this point you have all this figured out already as you are using it, I've tried to briefly go through what is happening as it doesn't look like you know what is happening. To update the bullet you could add some code something like: var delta = performance.now() var update = function() { var now = performance.now() var delta = now - last bullet.update( delta ) last = now requestAnimationFrame( update ) } // Lets go update() This just sets up a loop that works out the current time difference between frames (delta) and passes it to the bullet instance update function, which, rather unhelpfully, simply updates some values by the time step. All you have to do to extend this is add a `render` method to the `Bullet` prototype and render it within the game loop you've just created. If all you ever needed was one bullet that moves diagonally across the screen then you are set, but, you had to complicate things by wanting multiple objects didn’t you? So now you have to handle a possibly mutable list of objects, no problem, there are various solutions you can use. One of those solutions is to use a factory function and keep all your objects in a big list: // @param max <Integer> // @returns <Integer> between 0 and `max` function random( max ) { return Math.random() * max | 0 } // Bullet master list var bullets = [] // Bullet factory var createBullet = function() { var bullet = new Bullet( random( 640 ), random( 480 ) ) bullets.push( bullet ) return bullet } This is a really simple implementation that places a bullet with a random position into a list of bullets, it additionally returns the newly created instance. For here, we'd need to change our `update` function to now handle a list of bullets (for brevity we'll omit the time step calculations): function update() { bullets.forEach( function( bullet ) { bullet.update() }) requestAnimationFrame( update ) } update() And finally we'll probably want some code to trigger that factory to create some bullets for us document.body.addEventListener( 'click', createBullet ) And you now have a way to create a bucket load of bullets. From here you can go on to make things more complicated, but, remember complexity is the work of the devil and the foolish (these could be the two most important quotes for developers). Some things you'd probably want to add at some stage could be removing/destroying objects, maybe use a linked list (learn it but it's slower in JS), maybe use pooling etc etc. I'm not a huge fan of this style of coding but it is a good way to get started with the basics of list management and object creation. Quote Link to comment Share on other sites More sharing options...
vmars316 Posted April 21, 2016 Author Share Posted April 21, 2016 Matt , Quote Up to this point you have all this figured out already as you are using it, I've tried to briefly go through what is happening as it doesn't look like you know what is happening. How true ! I'll work with this a while . Thank you very much ! Quote Link to comment Share on other sites More sharing options...
mattstyles Posted April 21, 2016 Share Posted April 21, 2016 22 minutes ago, vmars316 said: Thank you very much ! Pleasure, I hope it helps. Just so you know, this stuff is not easy, it will become easier for you but managing lists of frequently changing objects is not a trivial thing, neither is effectively creating and destroying objects! Quote Link to comment Share on other sites More sharing options...
vmars316 Posted April 21, 2016 Author Share Posted April 21, 2016 Matt , What's the differences between these two ? : var Bullet = function( x, y ) { this.name = 'bullet' this.x = x this.y = y this.update = function( dt ) { this.x += dt this.y += dt } } Bullet.prototype.update = function( dt ) { this.x += dt this.y += dt } I haven't used prototype before . Thanks Quote Link to comment Share on other sites More sharing options...
mattstyles Posted April 21, 2016 Share Posted April 21, 2016 Hi, Prototypal inheritance works differently to classical inheritance, with prototypal inheritance objects are copies and they share a reference to a prototype, this means the prototype actually exists. By attaching the `update` function to the prototype it is created just once, even if you have tens of thousands of bullets, the top one would create a new function for every instance. In practise it is likely (but not definite) that the JS interpreter would optimise so that there is not too much difference but it is also possible that further optimisations could be made by using the prototype version, as JS developers we don't have to care too much about how exactly this all happens but it is worth reading up on the subject. When the prototype update function is called it has the scope of the caller, thus `this` will correspond to what you probably think it should. However, scope is a tricky concept with JS as there are a few things that can change it, and as you learn it, you will have some (hopefully small) problems relating to scope. Thankfully, like most of JS, it is easier once you get a handle on it. Look up discussions about JS scope, Function.bind, Function.call and Function.apply. They are tricky (as far as JS goes) concepts that are staples of good JS developers. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.