-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphysics.js
More file actions
124 lines (110 loc) · 6.19 KB
/
physics.js
File metadata and controls
124 lines (110 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
window.Physics = (function() {
function closestToValue(v, a, b) {
return Math.abs(a - v) < Math.abs(b - v) ? a : b;
};
return {
runSystem: function(model) {
// gravity
model.getEntities().filter(function(entity) {
return entity.gravity && entity.dy !== undefined && entity.collisionType !== "held";
}).forEach(function(entity) {
entity.dy--;
});
// TODO: is there a good way to combine step x and step y? should we?
// step x
model.getEntities().filter(function(entity) {
return entity.x !== undefined && entity.y !== undefined && entity.dx !== undefined && entity.dy !== undefined && entity.collisionType !== "held";
}).forEach(function(entity) {
var distanceToNearestEntity,
nearEdge,
farEdge,
oldX;
distanceToNearestEntity = Infinity;
nearEdge = (entity.dx > 0) ? Entity.getLeft : Entity.getRight;
farEdge = (entity.dx > 0) ? Entity.getRight: Entity.getLeft;
model.getExtraEntities().filter(function(otherEntity) {
var otherEntityOverlapsEntityZone,
otherEntityInDirectionOfEntityMovement,
correctCollisionType;
otherEntityOverlapsEntityZone = Entity.getTop(entity) > Entity.getBottom(otherEntity) && Entity.getBottom(entity) < Entity.getTop(otherEntity);
otherEntityInDirectionOfEntityMovement = (nearEdge(otherEntity) - entity.x) * (farEdge(entity) - entity.x) >= 0;
// only collide between environment entities and actor entities. This way for example the player can overlap the camera to pick it up while both are
// colliding with the ground.
correctCollisionType = (entity.collisionType === "environment" && otherEntity.collisionType === "actor") ||
(entity.collisionType === "actor" && otherEntity.collisionType === "environment");
return otherEntity !== entity && otherEntityOverlapsEntityZone && otherEntityInDirectionOfEntityMovement && correctCollisionType;
}).forEach(function(otherEntity) {
var distanceToOtherEntity;
distanceToOtherEntity = nearEdge(otherEntity) - farEdge(entity);
distanceToNearestEntity = closestToValue(0, distanceToOtherEntity, distanceToNearestEntity);
});
entity.x += closestToValue(0, distanceToNearestEntity, entity.dx);
if(entity.heldEntity !== undefined) {
entity.heldEntity.x += closestToValue(0, distanceToNearestEntity, entity.dx);
}
if(entity.wraps === true) {
// model.getCamera().x is center of screen
// model.getCamera().x - model.getView().width / 2 is left edge of screen
// entity.x - (model.getCamera().x - model.getView().width / 2) is distance from player to left edge of screen
// (distance + model.getView().width) % model.getView().width is wrapped distance
// wrapped distance + (model.getCamera().x - model.getView().width / 2) is wrapped player position
entity.x = (entity.x - model.getCamera().x + model.getView().width + model.getView().width / 2) % model.getView().width + model.getCamera().x - model.getView().width / 2;
// model.getCamera().x is center of screen
// model.getCamera().x + model.getView().width / 2 is right edge of screen
// entity.x - (model.getCamera().x + model.getView().width / 2) is distance from player to right edge of screen
// distance % width is wrapped distance // distance is always positive
// wrapped distance + (model.getCamera().x + model.getView().width / 2) is wrapped player position
//entity.x = (entity.x - model.getCamera().x - model.getView().width / 2) % model.getView().width + model.getCamera().x + model.getView().width / 2;
if(entity.heldEntity !== undefined) {
entity.heldEntity.x = (entity.heldEntity.x - model.getCamera().x + model.getView().width + model.getView().width / 2) % model.getView().width + model.getCamera().x - model.getView().width / 2;
//entity.heldEntity.x = (entity.heldEntity.x - model.getCamera().x - model.getView().width / 2) % model.getView().width + model.getCamera().x + model.getView().width / 2;
}
}
if(Math.abs(distanceToNearestEntity) < Math.abs(entity.dx)) {
entity.dx = 0;
}
});
// step y
model.getEntities().filter(function(entity) {
return entity.x !== undefined && entity.y !== undefined && entity.dx !== undefined && entity.dy !== undefined && entity.collisionType !== "held";
}).forEach(function(entity) {
var distanceToNearestEntity,
nearEdge,
farEdge;
distanceToNearestEntity = Infinity;
nearEdge = (entity.dy > 0) ? Entity.getBottom : Entity.getTop;
farEdge = (entity.dy > 0) ? Entity.getTop : Entity.getBottom;
model.getExtraEntities().filter(function(otherEntity) {
var otherEntityOverlapsEntityZone,
otherEntityInDirectionOfEntityMovement,
correctCollisionType;
otherEntityOverlapsEntityZone = Entity.getRight(entity) > Entity.getLeft(otherEntity) && Entity.getLeft(entity) < Entity.getRight(otherEntity);
otherEntityInDirectionOfEntityMovement = (nearEdge(otherEntity) - entity.y) * (farEdge(entity) - entity.y) >= 0;
// only collide between environment entities and actor entities. This way for example the player can overlap the camera to pick it up while both are
// colliding with the ground.
correctCollisionType = (entity.collisionType === "environment" && otherEntity.collisionType === "actor") ||
(entity.collisionType === "actor" && otherEntity.collisionType === "environment");
return entity !== otherEntity && otherEntityOverlapsEntityZone && otherEntityInDirectionOfEntityMovement && correctCollisionType;
}).forEach(function(otherEntity) {
var distanceToOtherEntity;
distanceToOtherEntity = nearEdge(otherEntity) - farEdge(entity);
distanceToNearestEntity = closestToValue(0, distanceToOtherEntity, distanceToNearestEntity);
});
entity.y += closestToValue(0, distanceToNearestEntity, entity.dy);
if(entity.heldEntity !== undefined) {
entity.heldEntity.y += closestToValue(0, distanceToNearestEntity, entity.dy);
}
if(Math.abs(distanceToNearestEntity) < Math.abs(entity.dy)) {
entity.dy = 0;
entity.landed = true;
}
});
model.getEntities().filter(function(entity) {
return entity.player;
}).forEach(function(entity) {
if(entity.y < 0)
model.restartLevel();
});
}
};
}());