Last active
May 1, 2016 20:05
-
-
Save PifyZ/dfbf9e6231adb22dacb7a1dcd50d363a to your computer and use it in GitHub Desktop.
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
shopt -s globstar | |
skewc src/**/*.sk --output-file=app.js --target=js --message-limit=0 |
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<meta | |
name="viewport" | |
content="width=device-width, initial-scale=1.0, user-scalable=no" | |
/> | |
<link rel="stylesheet" type="text/css" href="./web/css/style.css" /> | |
<title>Physics engine</title> | |
</head> | |
<body> | |
<canvas class="layer" id="app"></canvas> | |
<script src="./app.js"></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
const map = [ | |
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], | |
[ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ], | |
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] | |
] | |
class Point { | |
var x double | |
var y double | |
} | |
namespace Game { | |
const GRID = 20 | |
var hero Entity | |
} | |
namespace Entity { | |
var ALL = List<Entity>.new | |
} | |
class AABB { | |
var x double | |
var y double | |
var width double | |
var height double | |
def overlaps(r AABB) bool { | |
return x < r.x + r.width && x + width > r.x && | |
y < r.y + r.height && y + height > r.y | |
} | |
} | |
class Entity { | |
var repels bool | |
var radius double | |
var weight double | |
var dx double | |
var dy double | |
var killed bool | |
var cx double | |
var xr double | |
var cy double | |
var yr double | |
var xx int | |
var yy int | |
var frict double | |
def new(radius double) { | |
self.radius = radius | |
repels = true | |
cx = 5 | |
cy = 5 | |
xr = 0.5 | |
yr = 0.5 | |
xx = 0 | |
yy = 0 | |
weight = 1 | |
killed = false | |
frict = 0.98 | |
} | |
def aabb AABB { | |
return AABB.new(xx - radius, yy - radius, radius * 2, radius * 2) | |
} | |
def update { | |
if repels { | |
for e in ALL { | |
if e != self && !e.killed && e.repels && isClose(e) { | |
var pt = getPoint | |
var ept = e.getPoint | |
var d = distance(pt.x, pt.y, ept.x, ept.y) | |
var min = radius + e.radius | |
if d < min { | |
var angle = Math.atan2(e.yy - yy, e.xx - xx) / Math.PI | |
var conflict = min - d | |
var w = weight / (weight + e.weight) | |
var ew = e.weight / (weight + e.weight) | |
if angle >= 0.25 && angle < 0.75 { | |
dy -= (conflict / Game.GRID) * ew | |
e.dy += (conflict / Game.GRID) * w | |
} else if angle >= -0.75 && angle < -0.25 { | |
dy += (conflict / Game.GRID) * ew | |
e.dy -= (conflict / Game.GRID) * w | |
} else if angle >= -0.25 && angle < 0.25 { | |
dx -= (conflict / Game.GRID) * ew | |
e.dx += (conflict / Game.GRID) * w | |
} else if (angle >= -1 && angle < -0.75) || (angle > 0.75 && angle < 1) { | |
dx += (conflict / Game.GRID) * ew | |
e.dx -= (conflict / Game.GRID) * w | |
} | |
### | |
dx -= Math.cos(a) * (conflict / Game.GRID) * ew | |
dy -= Math.sin(a) * (conflict / Game.GRID) * ew | |
e.dx += Math.cos(a) * (conflict / Game.GRID) * w | |
e.dy += Math.sin(a) * (conflict / Game.GRID) * w | |
if e == Game.hero { | |
onHeroContact | |
} | |
### | |
} | |
} | |
} | |
} | |
xr += dx | |
dx *= frict | |
while xr < 0 { | |
cx-- | |
xr++ | |
} | |
while xr > 1 { | |
cx++ | |
xr-- | |
} | |
yr += dy | |
dy *= frict | |
while yr < 0 { | |
cy-- | |
yr++ | |
} | |
while yr > 1 { | |
cy++ | |
yr-- | |
} | |
xx = (cx * Game.GRID + xr * Game.GRID) as int | |
yy = (cy * Game.GRID + yr * Game.GRID) as int | |
} | |
def isClose(e Entity) bool { | |
return Math.abs(cx - e.cx) <= 2 && Math.abs(cy - e.cy) <= 2 | |
} | |
def getPoint Point { | |
return Point.new((cx + xr) * Game.GRID, (cy + yr) * Game.GRID) | |
} | |
def distance(x1 double, y1 double, x2 double, y2 double) double { | |
return Math.sqrt((x1 - x2) ** 2 + ((y1 - y2) ** 2)) | |
} | |
def onHeroContact { | |
} | |
def draw(ctx CanvasRenderingContext2D) { | |
ctx.drawImage(Img.get("crate"), xx - radius, yy - radius) | |
# ctx.fillRect(aabb.x, aabb.y, aabb.width, aabb.height) | |
### | |
ctx.fillStyle = "rgb(0, 255, 0)" | |
ctx.beginPath | |
ctx.arc(xx, yy, radius, 0, Math.PI * 2) | |
ctx.fill | |
### | |
} | |
} | |
class Player : Entity { | |
over draw(ctx CanvasRenderingContext2D) { | |
ctx.drawImage(Img.get("player"), 0, 0, 14, 15, xx - radius, yy - radius, 14, 15) | |
# ctx.fillRect(aabb.x, aabb.y, aabb.width, aabb.height) | |
### | |
ctx.fillStyle = "rgb(0, 255, 0)" | |
ctx.beginPath | |
ctx.arc(xx, yy, radius, 0, Math.PI * 2) | |
ctx.fill | |
### | |
} | |
} | |
# APPLICATION | |
# ----------- | |
var ctx CanvasRenderingContext2D | |
var kb = input.Keyboard.new | |
def tick { | |
Entity.ALL[2].dx = 0 | |
Entity.ALL[2].dy = 0 | |
if kb.down(Key.Left) { | |
Entity.ALL[2].dx -= 0.2 | |
} | |
if kb.down(Key.Right) { | |
Entity.ALL[2].dx += 0.2 | |
} | |
if kb.down(Key.Up) { | |
Entity.ALL[2].dy -= 0.2 | |
} | |
if kb.down(Key.Down) { | |
Entity.ALL[2].dy += 0.2 | |
} | |
ctx.clearRect(0, 0, 640, 480) | |
for y in 0 .. map.count - 1 { | |
for x in 0 .. map[y].count - 1 { | |
if map[y][x] == 1 { | |
ctx.fillRect(x * Game.GRID, y * Game.GRID, Game.GRID, Game.GRID) | |
} | |
} | |
} | |
for entity in Entity.ALL { | |
entity.update | |
} | |
for entity in Entity.ALL { | |
entity.draw(ctx) | |
} | |
requestAnimationFrame(=> tick) | |
} | |
@entry | |
def main { | |
var images = { | |
"player": "player.png", | |
"wall": "wall.png", | |
"ground": "ground.png", | |
"font": "font.png", | |
"font2": "font2.png", | |
"barrel": "block-barrel.png", | |
"mine": "block-mine.png", | |
"dynamite": "block-dynamite.png", | |
"crate": "block-crate.png", | |
"bullet": "bullet-normal.png", | |
"rocketLauncherBullet": "bullet-rocket-launcher.png", | |
"grenade": "bullet-grenade.png", | |
"miniatures": "miniatures-weapons.png", | |
"bonusIncreaseHealth": "bonus-increase-health.png" | |
} | |
Img.setPath("assets/img") | |
Img.setCallback(=> run) | |
Img.load(images) | |
} | |
def run { | |
var canvas = document.getElementById("app") as HTMLCanvasElement | |
canvas.width = 640 | |
canvas.height = 480 | |
ctx = canvas.getContext2D | |
Entity.ALL.append(Entity.new(12)) | |
Entity.ALL.append(Entity.new(12)) | |
Entity.ALL.append(Player.new(7)) | |
Game.hero = Entity.ALL[2] | |
Entity.ALL[0].cx = 25 | |
Entity.ALL[0].cy = 16 | |
Entity.ALL[0].weight = 20 | |
Entity.ALL[0].frict = 0 | |
Entity.ALL[1].cx = 18 | |
Entity.ALL[1].cy = 11 | |
Entity.ALL[1].weight = 20 | |
Entity.ALL[1].frict = 0 | |
Entity.ALL[2].weight = 10 | |
tick | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment