so://phie

game-engine

A lightweight JavaScript game engine
git clone git://soophie.de/game-engine

blob: b656063666049e010b15cb3c3abf7cd6d188938a (3095 bytes)[doc][blame][raw]

1import { scaleCanvas } from './canvas.js';

2import * as Collision from './collision.js';

3

4export class Game {

5 constructor(width, height, { fps } = {}) {

6 this.width = width || 900;

7 this.height = height || 600;

8 this.fps = 1000 / (fps || 60);

9 this.then = Date.now();

10 this.canvas = document.createElement('canvas');

11 scaleCanvas(this.canvas, this.width, this.height);

12 this.g = this.canvas.getContext('2d');

13 }

14 start() {

15 requestAnimationFrame(this.loop.bind(this));

16 this.update();

17 this.g.save();

18 this.render(this.g);

19 this.g.restore();

20 }

21 loop() {

22 requestAnimationFrame(this.loop.bind(this));

23 this.now = Date.now();

24 this.elapsed = this.now - this.then;

25 if(this.elapsed > this.fps) {

26 this.then = this.now - (this.elapsed % this.fps);

27 this.update();

28 this.g.save();

29 this.render(this.g);

30 this.g.restore();

31 }

32 }

33 update() {

34 // empty

35 }

36 render() {

37 this.g.clearRect(0, 0, this.width, this.height);

38 }

39 resize(width, height) {

40 this.width = width;

41 this.height = height;

42 scaleCanvas(this.canvas, this.width, this.height);

43 }

44}

45

46export class Group {

47 constructor() {

48 this.items = [];

49 }

50 update() {

51 for(let item of this.items) {

52 item.update();

53 }

54 }

55 render(g) {

56 for(let item of this.items) {

57 g.save();

58 item.render(g);

59 g.restore();

60 }

61 }

62 collide() {

63 for(const i of this.items) {

64 i.items = [];

65 i.collided = false;

66 }

67 const duplicate = [];

68 for(const a of this.items) {

69 for(const b of this.items) {

70 if(!duplicate.includes(b)) {

71 if(a !== b) {

72 let collided = false;

73 if(a.shape instanceof Shape.Rect && b.shape instanceof Shape.Rect) {

74 collided = Collision.collideRect(a, b);

75 }

76 else if(a.shape instanceof Shape.Circle && b.shape instanceof Shape.Circle) {

77 collided = Collision.collideCircle(a, b);

78 }

79 else {

80 collided = Collision.collideRectAndCircle(a, b);

81 }

82 if(!a.collided) {

83 a.collided = collided;

84 }

85 if(!b.collided) {

86 b.collided = collided;

87 }

88 if(collided) {

89 if(!a.items.includes(b)) {

90 a.items.push(b);

91 }

92 if(!b.items.includes(a)) {

93 b.items.push(a);

94 }

95 }

96 }

97 }

98 }

99 duplicate.push(a);

100 }

101 }

102 add(item) {

103 this.items.push(item);

104 }

105 remove(item) {

106 const i = this.items.findIndex(n => n === target);

107 if(i !== -1) {

108 this.items.splice(i, 1);

109 }

110 }

111 [Symbol.iterator]() {

112 return this.items.values();

113 }

114}

115

116export class Surface {

117 constructor(x, y, shape) {

118 this.x = x;

119 this.y = y;

120 this.shape = shape;

121 }

122 update() {

123 // empty

124 }

125 render(g) {

126 if(this.shape instanceof Shape.Rect) {

127 g.beginPath();

128 g.rect(this.x, this.y, this.shape.width, this.shape.height);

129 g.stroke();

130 }

131 if(this.shape instanceof Shape.Circle) {

132 g.beginPath();

133 g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);

134 g.stroke();

135 }

136 }

137}

138

139class Rect {

140 constructor(width, height) {

141 this.width = width;

142 this.height = height;

143 }

144}

145

146class Circle {

147 constructor(radius) {

148 this.radius = radius;

149 }

150}

151