Jump to content

Need help setting up bullet object in my game


vmars316
 Share

Recommended Posts

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

 

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...