-
-
Notifications
You must be signed in to change notification settings - Fork 643
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#285] new me.collision.rayCast function for basic Line of Sight impl…
…ementation this one was basically coming for free after we added Quadtree + SAT collision implementation in melonJS. it can probably be improved or the API tweaked a bit, but it's pretty simple to use already : just cast a line, and get in return an array of intersecting entities.
- Loading branch information
Showing
7 changed files
with
377 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
body { | ||
background-color: #000; | ||
color: #fff; | ||
|
||
/* Allow mouse dragging. */ | ||
-moz-user-select: none; | ||
-ms-user-select: none; | ||
-o-user-select: none; | ||
-webkit-user-select: none; | ||
user-select: none; | ||
|
||
/* disable touch panning/zooming */ | ||
-ms-touch-action: none; | ||
touch-action: none; | ||
|
||
/* Allow canvas to hit the edges of the browser viewport. */ | ||
margin: 0; | ||
} | ||
|
||
#screen canvas { | ||
margin: auto; | ||
|
||
/* Hide the gap for font descenders. */ | ||
display: block; | ||
|
||
/* disable scaling interpolation */ | ||
image-rendering: optimizeSpeed; | ||
image-rendering: -moz-crisp-edges; | ||
image-rendering: -o-crisp-edges; | ||
image-rendering: -webkit-optimize-contrast; | ||
image-rendering: optimize-contrast; | ||
image-rendering: pixelated; | ||
-ms-interpolation-mode: nearest-neighbor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>melonJS - Line Of Sight</title> | ||
<link rel="stylesheet" type="text/css" media="screen" href="index.css"> | ||
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | ||
<meta name="apple-mobile-web-app-capable" content="yes"> | ||
<meta name="apple-mobile-web-app-status-bar-style" content="black"> | ||
</head> | ||
<body> | ||
<!-- Canvas placeholder --> | ||
<div id="screen"></div> | ||
|
||
<!-- melonJS Library --> | ||
<script type="text/javascript" src="../../build/melonjs.js"></script> | ||
<script type="text/javascript" src="../../plugins/debug/debugPanel.js"></script> | ||
|
||
<!-- Game Scripts --> | ||
<script type="text/javascript" src="js/game.js"></script> | ||
<script type="text/javascript" src="js/entities/entities.js"></script> | ||
<script type="text/javascript" src="js/screens/play.js"></script> | ||
|
||
<!-- Bootstrap --> | ||
<script type="text/javascript"> | ||
me.device.onReady(function onReady() { | ||
game.onload(); | ||
}); | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
|
||
// a draggable square entity | ||
game.Square = me.Entity.extend({ | ||
/** | ||
* constructor | ||
*/ | ||
init: function (x, y, settings) { | ||
// ensure we do not create a default shape | ||
//settings.shapes = []; | ||
// call the super constructor | ||
this._super(me.Entity, "init", [x, y, settings]); | ||
|
||
//this.body.addShape(new me.Rect(x, y, this.width, this.height)); | ||
|
||
// status flags | ||
this.selected = false; | ||
this.hover = false; | ||
|
||
// to memorize where we grab the shape | ||
this.grabOffset = new me.Vector2d(0,0); | ||
|
||
// turn red once touched by a line | ||
this.color = new me.Color(0, 255, 0); | ||
|
||
this.isColliding = false; | ||
}, | ||
|
||
onActivateEvent: function () { | ||
//register on mouse/touch event | ||
me.input.registerPointerEvent("pointerdown", this, this.onSelect.bind(this)); | ||
me.input.registerPointerEvent("pointerup", this, this.onRelease.bind(this)); | ||
me.input.registerPointerEvent("pointercancel", this, this.onRelease.bind(this)); | ||
me.input.registerPointerEvent("pointermove", this, this.pointerMove.bind(this)); | ||
}, | ||
|
||
/** | ||
* pointermove function | ||
*/ | ||
pointerMove: function (event) { | ||
if (this.selected) { | ||
// follow the pointer | ||
me.game.world.moveUp(this); | ||
this.pos.set(event.gameX, event.gameY, this.pos.z); | ||
this.pos.sub(this.grabOffset); | ||
} | ||
}, | ||
|
||
|
||
// mouse down function | ||
onSelect : function (event) { | ||
if (this.selected === false) { | ||
// manually calculate the relative coordinates for the body shapes | ||
// since only the bounding box is used by the input event manager | ||
var parentPos = this.ancestor.getBounds().pos; | ||
var x = event.gameX - this.pos.x - parentPos.x; | ||
var y = event.gameY - this.pos.y - parentPos.y; | ||
|
||
// the pointer event system will use the object bounding rect, check then with with all defined shapes | ||
for (var i = this.body.shapes.length, shape; i--, (shape = this.body.shapes[i]);) { | ||
if (shape.containsPoint(x, y)) { | ||
this.selected = true; | ||
break; | ||
} | ||
} | ||
if (this.selected) { | ||
this.grabOffset.set(event.gameX, event.gameY); | ||
this.grabOffset.sub(this.pos); | ||
this.selected = true; | ||
} | ||
} | ||
return this.seleted; | ||
}, | ||
|
||
// mouse up function | ||
onRelease : function (/*event*/) { | ||
this.selected = false; | ||
// don"t propagate the event furthermore | ||
return false; | ||
}, | ||
|
||
/** | ||
* update function | ||
*/ | ||
update: function () { | ||
return true; | ||
}, | ||
|
||
/** | ||
* draw the square | ||
*/ | ||
draw: function (renderer) { | ||
var lineWidth = 2; | ||
|
||
if (this.isColliding === true) { | ||
this.color.setColor(255, 0, 0); | ||
} else { | ||
this.color.setColor(0, 255, 0); | ||
} | ||
|
||
renderer.setGlobalAlpha(0.5); | ||
renderer.setColor(this.color); | ||
renderer.fillRect(0, 0, this.width, this.height); | ||
renderer.setGlobalAlpha(1.0); | ||
renderer.setLineWidth(lineWidth); | ||
renderer.strokeRect( | ||
lineWidth, | ||
lineWidth, | ||
this.width - lineWidth * 2, | ||
this.height - lineWidth * 2 | ||
); | ||
|
||
// reset the colliding flag | ||
this.isColliding = false; | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
/* Game namespace */ | ||
var game = { | ||
// Run on page load. | ||
"onload" : function () { | ||
// Initialize the video. | ||
if (!me.video.init(800, 600, {wrapper : "screen", scale : "auto", renderer : me.video.CANVAS})) { | ||
alert("Your browser does not support HTML5 canvas."); | ||
return; | ||
} | ||
|
||
// set the "Play/Ingame" Screen Object | ||
me.state.set(me.state.PLAY, new game.PlayScreen()); | ||
|
||
// add some keyboard shortcuts | ||
me.event.subscribe(me.event.KEYDOWN, function (action, keyCode /*, edge */) { | ||
|
||
// toggle fullscreen on/off | ||
if (keyCode === me.input.KEY.F) { | ||
if (!me.device.isFullscreen) { | ||
me.device.requestFullscreen(); | ||
} else { | ||
me.device.exitFullscreen(); | ||
} | ||
} | ||
}); | ||
|
||
// render hitbox int the debug panel | ||
me.debug.renderHitBox = true; | ||
|
||
// switch to PLAY state | ||
me.state.change(me.state.PLAY); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
game.PlayScreen = me.ScreenObject.extend({ | ||
/** | ||
* action to perform on state change | ||
*/ | ||
onResetEvent: function() { | ||
var rectSize = 150; | ||
|
||
// clear the background | ||
me.game.world.addChild(new me.ColorLayer("background", "black"), 0); | ||
|
||
// add a few shapes | ||
me.game.world.addChild(new game.Square(50, 50, {width: rectSize, height: rectSize}), 1); | ||
me.game.world.addChild(new game.Square(50, 400, {width: rectSize, height: rectSize}), 1); | ||
me.game.world.addChild(new game.Square(300, 150, {width: rectSize, height: rectSize}), 1); | ||
me.game.world.addChild(new game.Square(300, 350, {width: rectSize, height: rectSize}), 1); | ||
me.game.world.addChild(new game.Square(600, 200, {width: rectSize, height: rectSize}), 1); | ||
me.game.world.addChild(new game.Square(600, 400, {width: rectSize, height: rectSize}), 1); | ||
|
||
me.game.repaint(); | ||
|
||
// display the current pointer coordinates on top of the pointer arrow | ||
// and some helper text at the bottom of the viewport | ||
me.game.world.addChild(new (me.Renderable.extend({ | ||
init: function() { | ||
this._super(me.Renderable, 'init', [0, 0, 10, 10]); | ||
this.font = new me.Font("Arial", 10, "#FFFFFF"); | ||
this.font.textAlign = "center"; | ||
this.fontHeight = this.font.measureText(me.video.renderer, "DUMMY").height; | ||
}, | ||
update : function (dt) { | ||
return true; | ||
}, | ||
draw: function(renderer) { | ||
var x = Math.round(me.input.pointer.gameWorldX); | ||
var y = Math.round(me.input.pointer.gameWorldY); | ||
|
||
this.font.draw ( | ||
renderer, | ||
"( " + x + "," + y + " )", | ||
x, | ||
y - this.fontHeight); | ||
|
||
this.font.draw ( | ||
renderer, | ||
"drag the square to check for intersection witht the line", | ||
150, | ||
me.game.viewport.height - this.fontHeight | ||
); | ||
} | ||
})), 10); | ||
|
||
// basic renderable that cast a ray across the world | ||
me.game.world.addChild(new (me.Renderable.extend({ | ||
init: function() { | ||
this._super(me.Renderable, 'init', [0, 0, 10, 10]); | ||
this.line = new me.Line(0, 0, [ | ||
new me.Vector2d(0, 0), | ||
new me.Vector2d(me.game.viewport.width, me.game.viewport.height) | ||
]); | ||
|
||
}, | ||
update : function (dt) { | ||
var result = me.collision.rayCast(this.line); | ||
|
||
if (result.length > 0) { | ||
for (i = 0; i < result.length; i++) { | ||
// update the object isColliding flag | ||
result[i].isColliding = true; | ||
} | ||
} | ||
return true; | ||
}, | ||
draw: function(renderer) { | ||
renderer.setColor("red"); | ||
renderer.drawShape(this.line); | ||
} | ||
})), 10); | ||
} | ||
}); |
Oops, something went wrong.