slifer 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/Logo.png +0 -0
- package/README.md +59 -0
- package/bun.lockb +0 -0
- package/index.ts +4 -0
- package/libs/libSDL2.dll +0 -0
- package/libs/libSDL2.dylib +0 -0
- package/libs/libSDL2_gfx.dylib +0 -0
- package/libs/libSDL2_image.dll +0 -0
- package/libs/libSDL2_image.dylib +0 -0
- package/libs/libSDL2_ttf.dll +0 -0
- package/libs/libSDL2_ttf.dylib +0 -0
- package/logo-alpha.png +0 -0
- package/package.json +14 -0
- package/src/ffi.ts +213 -0
- package/src/global.ts +10 -0
- package/src/modules/graphics.ts +156 -0
- package/src/modules/keyboard.ts +78 -0
- package/src/modules/mouse.ts +100 -0
- package/src/slifer.ts +115 -0
- package/tsconfig.json +27 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Mohammed Salim
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/Logo.png
ADDED
Binary file
|
package/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Slifer : Native Typescript Game Framework
|
2
|
+
|
3
|
+
<p align="center">
|
4
|
+
<img width="80%" src="./logo-alpha.png">
|
5
|
+
</p>
|
6
|
+
|
7
|
+
> [!CAUTION]
|
8
|
+
> Slifer is currently in alpha. Use at your own risk.
|
9
|
+
>
|
10
|
+
|
11
|
+
> [!NOTE]
|
12
|
+
> Not all basic features have been implemented. Many are missing such as window customization.
|
13
|
+
> As such, I recommend waiting for a beta release of Slifer before using it for a long term project.
|
14
|
+
|
15
|
+
Slifer is a game framework made to allow users to code games in typescript. The framework uses bun and SDL2 under the hood to allow your game to render and build natively to desktop.
|
16
|
+
|
17
|
+
## Contents
|
18
|
+
- [Goals](#goals)
|
19
|
+
- [Current Features](#current-features)
|
20
|
+
- [Future Features](#future-features)
|
21
|
+
- [Example](#example)
|
22
|
+
|
23
|
+
## Goals
|
24
|
+
|
25
|
+
- Contain all basic game framework implementations. Such as drawing images, drawing text and making animations from a sprite sheet.
|
26
|
+
- Provide an easy transition from web development to game development.
|
27
|
+
- Create an easy to use framework. Slifer should handle the bulk of the work
|
28
|
+
- Keep updates consistent.
|
29
|
+
|
30
|
+
## Current Features
|
31
|
+
- Create a native desktop window with custom title and size.
|
32
|
+
- Handle both keyboard and mouse inputs
|
33
|
+
- Load and draw images onto the window
|
34
|
+
|
35
|
+
## Future Features
|
36
|
+
- Audio Implementation
|
37
|
+
- Animation library
|
38
|
+
- Save file library
|
39
|
+
|
40
|
+
## Example
|
41
|
+
```ts
|
42
|
+
import Slifer from Slifer;
|
43
|
+
|
44
|
+
Slifer.createWindow("Example Window", 640, 480);
|
45
|
+
|
46
|
+
const bg = Slifer.Graphics.makeColor(36, 36, 36, 255);
|
47
|
+
|
48
|
+
while (!Slifer.shouldClose()) {
|
49
|
+
Slifer.Graphics.setBackground(bg);
|
50
|
+
|
51
|
+
if (Slifer.Keyboard.isPressed('escape')) {
|
52
|
+
Slifer.isRunning = false;
|
53
|
+
}
|
54
|
+
|
55
|
+
Slifer.Graphics.render();
|
56
|
+
}
|
57
|
+
|
58
|
+
Slifer.quit();
|
59
|
+
```
|
package/bun.lockb
ADDED
Binary file
|
package/index.ts
ADDED
package/libs/libSDL2.dll
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
package/logo-alpha.png
ADDED
Binary file
|
package/package.json
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"name": "slifer",
|
3
|
+
"version": "0.1.2",
|
4
|
+
"description": "A game framework made for bun and typescript",
|
5
|
+
"module": "index.ts",
|
6
|
+
"devDependencies": {
|
7
|
+
"@types/bun": "latest",
|
8
|
+
"typedoc": "^0.26.7"
|
9
|
+
},
|
10
|
+
"peerDependencies": {
|
11
|
+
"typescript": "^5.0.0"
|
12
|
+
},
|
13
|
+
"type": "module"
|
14
|
+
}
|
package/src/ffi.ts
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
import { dlopen, FFIType, suffix } from 'bun:ffi';
|
2
|
+
|
3
|
+
let libSDLImport;
|
4
|
+
let libImageImport;
|
5
|
+
let libTTFImport;
|
6
|
+
let libGFXImport;
|
7
|
+
|
8
|
+
if (process.platform == "win32") {
|
9
|
+
//@ts-expect-error
|
10
|
+
libSDLImport = await import("../libs/libSDL2.dll");
|
11
|
+
//@ts-expect-error
|
12
|
+
libImageImport = await import("../libs/libSDL2_image.dll");
|
13
|
+
//@ts-expect-error
|
14
|
+
libTTFImport = await import("../libs/libSDL2_ttf.dll");
|
15
|
+
} else if (process.platform == "darwin") {
|
16
|
+
//@ts-expect-error
|
17
|
+
libSDLImport = await import("../libs/libSDL2.dylib");
|
18
|
+
//@ts-expect-error
|
19
|
+
libImageImport = await import("../libs/libSDL2_image.dylib");
|
20
|
+
//@ts-expect-error
|
21
|
+
libTTFImport = await import("../libs/libSDL2_ttf.dylib");
|
22
|
+
}
|
23
|
+
|
24
|
+
export const libsdl = dlopen(libSDLImport.default, {
|
25
|
+
SDL_Init: {
|
26
|
+
args: [FFIType.int],
|
27
|
+
returns: FFIType.int
|
28
|
+
},
|
29
|
+
SDL_GetRevision: {
|
30
|
+
returns: 'cstring'
|
31
|
+
},
|
32
|
+
SDL_CreateWindow: {
|
33
|
+
args: ['cstring', 'int', 'int', 'int', 'int', 'u32'],
|
34
|
+
returns: 'pointer'
|
35
|
+
},
|
36
|
+
SDL_CreateRenderer: {
|
37
|
+
args: ['pointer', 'int', 'u32'],
|
38
|
+
returns: 'pointer'
|
39
|
+
},
|
40
|
+
SDL_GetDesktopDisplayMode: {
|
41
|
+
args: ['int', 'pointer'],
|
42
|
+
returns: 'int'
|
43
|
+
},
|
44
|
+
SDL_GetDisplayOrientation: {
|
45
|
+
args: ['int'],
|
46
|
+
returns: 'int'
|
47
|
+
},
|
48
|
+
SDL_SetWindowFullscreen: {
|
49
|
+
args: ['pointer', 'u32'],
|
50
|
+
returns: 'int'
|
51
|
+
},
|
52
|
+
SDL_PollEvent: {
|
53
|
+
args: ['pointer'],
|
54
|
+
returns: 'int'
|
55
|
+
},
|
56
|
+
SDL_RenderClear: {
|
57
|
+
args: ['pointer'],
|
58
|
+
returns: 'int'
|
59
|
+
},
|
60
|
+
SDL_RenderCopy: {
|
61
|
+
args: ['pointer', 'pointer', 'pointer', 'pointer'],
|
62
|
+
returns: 'int'
|
63
|
+
},
|
64
|
+
SDL_RenderPresent: {
|
65
|
+
args: ['pointer'],
|
66
|
+
returns: 'void'
|
67
|
+
},
|
68
|
+
SDL_CreateTextureFromSurface: {
|
69
|
+
args: ['pointer', 'pointer'],
|
70
|
+
returns: 'pointer'
|
71
|
+
},
|
72
|
+
SDL_DestroyRenderer: {
|
73
|
+
args: ['pointer'],
|
74
|
+
returns: 'void'
|
75
|
+
},
|
76
|
+
SDL_DestroyWindow: {
|
77
|
+
args: ['pointer'],
|
78
|
+
returns: 'void'
|
79
|
+
},
|
80
|
+
SDL_Quit: {
|
81
|
+
returns: 'void'
|
82
|
+
},
|
83
|
+
SDL_GetKeyName: {
|
84
|
+
args: ['int'],
|
85
|
+
returns: 'cstring'
|
86
|
+
},
|
87
|
+
SDL_GetKeyFromScancode: {
|
88
|
+
args: ['int'],
|
89
|
+
returns: 'int'
|
90
|
+
},
|
91
|
+
SDL_GetPerformanceCounter: {
|
92
|
+
returns: 'u64'
|
93
|
+
},
|
94
|
+
SDL_GetPerformanceFrequency: {
|
95
|
+
returns: 'u64'
|
96
|
+
},
|
97
|
+
SDL_QueryTexture :{
|
98
|
+
args: ['pointer', 'pointer', 'pointer', 'pointer', 'pointer'],
|
99
|
+
returns: 'int'
|
100
|
+
},
|
101
|
+
SDL_GetMouseState: {
|
102
|
+
args: ['pointer', 'pointer'],
|
103
|
+
returns: 'u32'
|
104
|
+
},
|
105
|
+
SDL_CreateColorCursor: {
|
106
|
+
args: ['pointer', 'int', 'int'],
|
107
|
+
returns: 'pointer'
|
108
|
+
},
|
109
|
+
SDL_SetCursor: {
|
110
|
+
args: ['pointer'],
|
111
|
+
returns: 'void'
|
112
|
+
},
|
113
|
+
SDL_SetRenderDrawColor: {
|
114
|
+
args: ['pointer', 'int', 'int', 'int', 'int'],
|
115
|
+
returns: 'void'
|
116
|
+
},
|
117
|
+
SDL_RenderFillRect: {
|
118
|
+
args: ['pointer', 'pointer'],
|
119
|
+
returns: 'bool'
|
120
|
+
},
|
121
|
+
SDL_GetWindowPosition: {
|
122
|
+
args: ['pointer', 'pointer', 'pointer'],
|
123
|
+
returns: 'void'
|
124
|
+
},
|
125
|
+
SDL_SetWindowPosition: {
|
126
|
+
args: ['pointer', 'int', 'int'],
|
127
|
+
returns: 'void'
|
128
|
+
},
|
129
|
+
SDL_SetWindowHitTest: {
|
130
|
+
args: ['pointer', FFIType.function, 'pointer'],
|
131
|
+
returns: 'int'
|
132
|
+
},
|
133
|
+
SDL_GetWindowSize: {
|
134
|
+
args: ['pointer', 'pointer', 'pointer'],
|
135
|
+
returns: 'void'
|
136
|
+
},
|
137
|
+
SDL_CreateSystemCursor: {
|
138
|
+
args:['int'],
|
139
|
+
returns: 'pointer'
|
140
|
+
},
|
141
|
+
SDL_GetError: {
|
142
|
+
returns: 'cstring'
|
143
|
+
},
|
144
|
+
SDL_SetHint: {
|
145
|
+
args: ['cstring', 'cstring'],
|
146
|
+
returns: 'bool'
|
147
|
+
},
|
148
|
+
SDL_MinimizeWindow: {
|
149
|
+
args: ['pointer'],
|
150
|
+
returns: 'void'
|
151
|
+
},
|
152
|
+
SDL_GetShapedWindowMode: {
|
153
|
+
args: ['pointer', 'pointer'],
|
154
|
+
returns: 'int'
|
155
|
+
},
|
156
|
+
SDL_CreateShapedWindow: {
|
157
|
+
args: ['cstring', 'int', 'int', 'int', 'int', 'u32'],
|
158
|
+
returns: 'pointer'
|
159
|
+
},
|
160
|
+
SDL_SetWindowShape: {
|
161
|
+
args: ['pointer', 'pointer', 'pointer'],
|
162
|
+
returns: 'int'
|
163
|
+
},
|
164
|
+
SDL_SetWindowIcon: {
|
165
|
+
args: ['pointer', 'pointer'],
|
166
|
+
returns: 'void'
|
167
|
+
},
|
168
|
+
SDL_RaiseWindow: {
|
169
|
+
args: ['pointer'],
|
170
|
+
returns: 'void'
|
171
|
+
},
|
172
|
+
SDL_RenderCopyEx: {
|
173
|
+
args: ['pointer', 'pointer', 'pointer', 'pointer', 'double', 'pointer', 'int'],
|
174
|
+
returns: 'int'
|
175
|
+
}
|
176
|
+
})
|
177
|
+
|
178
|
+
export const libimage = dlopen(libImageImport.default, {
|
179
|
+
IMG_Init: {
|
180
|
+
args: ['int'],
|
181
|
+
returns: 'int'
|
182
|
+
},
|
183
|
+
IMG_Load: {
|
184
|
+
args: ['cstring'],
|
185
|
+
returns: 'pointer'
|
186
|
+
}
|
187
|
+
})
|
188
|
+
|
189
|
+
export const libttf = dlopen(libTTFImport.default, {
|
190
|
+
TTF_Init: {
|
191
|
+
returns: 'int'
|
192
|
+
},
|
193
|
+
TTF_OpenFont: {
|
194
|
+
args: ['cstring', 'int'],
|
195
|
+
returns: 'pointer'
|
196
|
+
},
|
197
|
+
TTF_RenderText_Solid: {
|
198
|
+
args: ['pointer', 'cstring', 'u32'],
|
199
|
+
returns: 'pointer'
|
200
|
+
},
|
201
|
+
TTF_SizeText: {
|
202
|
+
args: ['pointer', 'cstring', 'pointer', 'pointer'],
|
203
|
+
returns: 'int'
|
204
|
+
},
|
205
|
+
TTF_Quit: {
|
206
|
+
returns: 'void'
|
207
|
+
},
|
208
|
+
TTF_CloseFont: {
|
209
|
+
args: ['pointer'],
|
210
|
+
returns: 'void'
|
211
|
+
}
|
212
|
+
|
213
|
+
})
|
package/src/global.ts
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
import { libimage, libsdl, libttf } from "../ffi";
|
2
|
+
import Global from "../global";
|
3
|
+
import { type Pointer, ptr } from 'bun:ffi';
|
4
|
+
import path from 'path';
|
5
|
+
|
6
|
+
class Graphics {
|
7
|
+
/**
|
8
|
+
* Slifers draw function. Used to draw everything to the screen.
|
9
|
+
*/
|
10
|
+
render() {
|
11
|
+
libsdl.symbols.SDL_RenderPresent(Global.ptrRenderer);
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Create a new color. All values are from 0-255
|
16
|
+
*
|
17
|
+
* @param r red value
|
18
|
+
* @param g green value
|
19
|
+
* @param b blue value
|
20
|
+
* @param a alpha value
|
21
|
+
* @returns Color object
|
22
|
+
*/
|
23
|
+
makeColor(r: number, g: number, b: number, a: number) {
|
24
|
+
const _color = new Color(r, g, b, a);
|
25
|
+
return _color;
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Sets the background of the window to a color of choice.
|
30
|
+
*
|
31
|
+
* Make sure this is put in the top level of the while loop
|
32
|
+
* as it will clear the renderer.
|
33
|
+
*
|
34
|
+
* @param color Color object. Make using Slifer.Graphics.makeColor
|
35
|
+
*/
|
36
|
+
setBackground(color: Color) {
|
37
|
+
libsdl.symbols.SDL_SetRenderDrawColor(Global.ptrRenderer, color.r, color.g, color.b, color.a);
|
38
|
+
libsdl.symbols.SDL_RenderClear(Global.ptrRenderer);
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Loads a new image
|
43
|
+
*
|
44
|
+
* @param path string path to image
|
45
|
+
* @returns Image ready to draw
|
46
|
+
*/
|
47
|
+
loadImage(path: string) : Image {
|
48
|
+
const _path = Buffer.from(path + "\x00");
|
49
|
+
const surface = libimage.symbols.IMG_Load(_path);
|
50
|
+
if (surface == null) throw `Image failed to load`;
|
51
|
+
const texture = libsdl.symbols.SDL_CreateTextureFromSurface(Global.ptrRenderer, surface);
|
52
|
+
if (texture == null) throw `Image failed to be created`;
|
53
|
+
return new Image(texture);
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Method to draw the image to the screen
|
58
|
+
*
|
59
|
+
* @param image Image object to draw. Made using Slifer.Graphics.loadImage
|
60
|
+
* @param x x position to draw image
|
61
|
+
* @param y y position to draw image
|
62
|
+
* @param rotation (optional) rotation of image
|
63
|
+
* @param xs (optional) scale of x axis
|
64
|
+
* @param ys (optional) scale of y axis
|
65
|
+
* @param flip (optional) horizontal flip
|
66
|
+
*/
|
67
|
+
draw(image: Image, x: number, y: number, rotation?: number, xs?: number, ys?: number, flip?: true) {
|
68
|
+
const _dest = new Uint32Array(4);
|
69
|
+
const wArr = new Uint32Array(1);
|
70
|
+
const hArr = new Uint32Array(1);
|
71
|
+
libsdl.symbols.SDL_QueryTexture((image as any).pointer, null, null, ptr(wArr), ptr(hArr));
|
72
|
+
_dest[0] = x;
|
73
|
+
_dest[1] = y;
|
74
|
+
_dest[2] = wArr[0] * (xs ? xs : 1);
|
75
|
+
_dest[3] = hArr[0] * (ys ? ys : 1);
|
76
|
+
const _center = new Uint32Array(2);
|
77
|
+
_center[0] = _dest[2] / 2;
|
78
|
+
_center[1] = _dest[3] / 2;
|
79
|
+
libsdl.symbols.SDL_RenderCopyEx(Global.ptrRenderer, (image as any).pointer, null, ptr(_dest), rotation ? rotation : 0, ptr(_center), flip ? Number(flip) : 0);
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Method to draw text to the screen
|
84
|
+
*
|
85
|
+
* @param text the string of text to print
|
86
|
+
* @param x x position
|
87
|
+
* @param y y position
|
88
|
+
* @param color color of text. Made using Slifer.Graphics.makeColor.
|
89
|
+
*/
|
90
|
+
print(text: string, x: number, y: number, color: Color) {
|
91
|
+
|
92
|
+
// Create text buffer
|
93
|
+
const textBuffer = Buffer.from(text+"\x00");
|
94
|
+
|
95
|
+
// Get width and height of text
|
96
|
+
const wArr = new Uint32Array(1);
|
97
|
+
const hArr = new Uint32Array(1);
|
98
|
+
libttf.symbols.TTF_SizeText(Global.ptrFont,textBuffer , ptr(wArr), ptr(hArr));
|
99
|
+
|
100
|
+
// Define color
|
101
|
+
const _col = ((color.r << 0) + (color.g << 8) + (color.b << 16));
|
102
|
+
|
103
|
+
// Create texture
|
104
|
+
const surface = libttf.symbols.TTF_RenderText_Solid(Global.ptrFont, textBuffer, _col);
|
105
|
+
if (surface == null) throw `Surface creation failed on print`;
|
106
|
+
const texture = libsdl.symbols.SDL_CreateTextureFromSurface(Global.ptrRenderer, surface);
|
107
|
+
if (texture == null) throw `Texture creation failed on print`;
|
108
|
+
|
109
|
+
// Create destination
|
110
|
+
const destArr = new Uint32Array(4);
|
111
|
+
destArr[0] = x;
|
112
|
+
destArr[1] = y;
|
113
|
+
destArr[2] = wArr[0];
|
114
|
+
destArr[3] = hArr[0];
|
115
|
+
|
116
|
+
// Draw text
|
117
|
+
libsdl.symbols.SDL_RenderCopy(Global.ptrRenderer, texture, null, ptr(destArr));
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Sets the font to a ttf file in your project
|
122
|
+
*
|
123
|
+
* @param path relative path to font
|
124
|
+
* @param pt size of text
|
125
|
+
*/
|
126
|
+
setFont(path: string, pt: number) {
|
127
|
+
const tempFont = libttf.symbols.TTF_OpenFont(Buffer.from(path+"\x00"), pt);
|
128
|
+
if (tempFont == null) throw `Font loading failed`;
|
129
|
+
Global.ptrFont = tempFont;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
class Image {
|
134
|
+
|
135
|
+
private pointer;
|
136
|
+
|
137
|
+
constructor(texture: Pointer) {
|
138
|
+
this.pointer = texture;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
class Color {
|
143
|
+
readonly r;
|
144
|
+
readonly g;
|
145
|
+
readonly b;
|
146
|
+
readonly a;
|
147
|
+
|
148
|
+
constructor(r: number, g: number, b: number, a: number) {
|
149
|
+
this.r = r;
|
150
|
+
this.g = g;
|
151
|
+
this.b = b;
|
152
|
+
this.a = a;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
export default Graphics;
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Keyboard {
|
2
|
+
|
3
|
+
static downKeyMap = new Map<string, boolean>();
|
4
|
+
static pressedKeyMap = new Map<string, boolean>();
|
5
|
+
static releasedKeyMap = new Map<string, boolean>();
|
6
|
+
|
7
|
+
static setKeyDown(key: string) {
|
8
|
+
this.downKeyMap.set(key, true);
|
9
|
+
this.releasedKeyMap.set(key, false);
|
10
|
+
}
|
11
|
+
|
12
|
+
static setKeyUp(key: string) {
|
13
|
+
this.downKeyMap.set(key, false);
|
14
|
+
this.pressedKeyMap.set(key, false);
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
*
|
19
|
+
* @param key string of key
|
20
|
+
* @returns if the key is being held down
|
21
|
+
*/
|
22
|
+
isDown(key: keys) {
|
23
|
+
const _state = Keyboard.downKeyMap.get(key);
|
24
|
+
if (_state == undefined) return false
|
25
|
+
|
26
|
+
return _state;
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
*
|
31
|
+
* @param key string of key
|
32
|
+
* @returns if key is pressed. Returns only once
|
33
|
+
*/
|
34
|
+
isPressed(key: keys) {
|
35
|
+
const _pressedState = Keyboard.pressedKeyMap.get(key);
|
36
|
+
const _downState = Keyboard.downKeyMap.get(key);
|
37
|
+
|
38
|
+
if (_downState == true) {
|
39
|
+
if (_pressedState == false || _pressedState == undefined) {
|
40
|
+
Keyboard.pressedKeyMap.set(key, true);
|
41
|
+
return true;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
*
|
50
|
+
* @param key string of key
|
51
|
+
* @returns if key is released. Returns only once
|
52
|
+
*/
|
53
|
+
isReleased(key: keys) {
|
54
|
+
const _releasedState = Keyboard.releasedKeyMap.get(key);
|
55
|
+
const _downState = Keyboard.downKeyMap.get(key);
|
56
|
+
|
57
|
+
if (_downState == false) {
|
58
|
+
if (_releasedState == false || undefined) {
|
59
|
+
Keyboard.releasedKeyMap.set(key, true);
|
60
|
+
return true;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
return false;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
type keys = 'a' |'b' |'c' |'d' |'e' |'f' |'g' |'h' |'i' |'j' |'k' |'l' |'m' |'n' |'o' |'p' |'q' |'r' |'s' |'t' |'u' |'v' |'w' |'x' |'y' |'z' |
|
69
|
+
'1' |'2' |'3' |'4' |'5' |'6' |'7' |'8' |'9' |'0' |
|
70
|
+
'space' |
|
71
|
+
'caps lock' |
|
72
|
+
'tab' |
|
73
|
+
'left shift' |
|
74
|
+
'right shift' |
|
75
|
+
'left ctrl' |
|
76
|
+
'escape';
|
77
|
+
|
78
|
+
export default Keyboard;
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import { libsdl } from "../ffi";
|
2
|
+
import { ptr } from 'bun:ffi';
|
3
|
+
|
4
|
+
class Mouse {
|
5
|
+
|
6
|
+
static downKeyMap = new Map<string, boolean>();
|
7
|
+
static pressedKeyMap = new Map<string, boolean>();
|
8
|
+
static releasedKeyMap = new Map<string, boolean>();
|
9
|
+
|
10
|
+
static setButtonDown(button: number) {
|
11
|
+
|
12
|
+
let key : string = '';
|
13
|
+
if (button == 1) {
|
14
|
+
key = "left";
|
15
|
+
} else if (button == 2) {
|
16
|
+
key = "middle";
|
17
|
+
} else {
|
18
|
+
key = "right";
|
19
|
+
}
|
20
|
+
|
21
|
+
this.downKeyMap.set(key, true);
|
22
|
+
this.releasedKeyMap.set(key, false);
|
23
|
+
}
|
24
|
+
|
25
|
+
static setButtonUp(button: number) {
|
26
|
+
|
27
|
+
let key : string = '';
|
28
|
+
if (button == 1) {
|
29
|
+
key = "left";
|
30
|
+
} else if (button == 2) {
|
31
|
+
key = "middle";
|
32
|
+
} else {
|
33
|
+
key = "right";
|
34
|
+
}
|
35
|
+
|
36
|
+
this.downKeyMap.set(key, false);
|
37
|
+
this.pressedKeyMap.set(key, false);
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
*
|
42
|
+
* @param button string of button
|
43
|
+
* @returns if the button is being held down
|
44
|
+
*/
|
45
|
+
isDown(button: buttons) {
|
46
|
+
const _state = Mouse.downKeyMap.get(button);
|
47
|
+
if (_state == undefined) return false
|
48
|
+
|
49
|
+
return _state;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
*
|
54
|
+
* @param button string of button
|
55
|
+
* @returns if button is pressed. Returns only once
|
56
|
+
*/
|
57
|
+
isPressed(button: buttons) {
|
58
|
+
const _pressedState = Mouse.pressedKeyMap.get(button);
|
59
|
+
const _downState = Mouse.downKeyMap.get(button);
|
60
|
+
|
61
|
+
if (_downState == true) {
|
62
|
+
if (_pressedState == false || _pressedState == undefined) {
|
63
|
+
Mouse.pressedKeyMap.set(button, true);
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
return false;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
*
|
73
|
+
* @param button string of button
|
74
|
+
* @returns if button is released. Returns only once
|
75
|
+
*/
|
76
|
+
isReleased(button: buttons) {
|
77
|
+
const _releasedState = Mouse.releasedKeyMap.get(button);
|
78
|
+
const _downState = Mouse.downKeyMap.get(button);
|
79
|
+
|
80
|
+
if (_downState == false) {
|
81
|
+
if (_releasedState == false || undefined) {
|
82
|
+
Mouse.releasedKeyMap.set(button, true);
|
83
|
+
return true;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
|
90
|
+
getPosition() {
|
91
|
+
const xArr = new Uint32Array(1);
|
92
|
+
const yArr = new Uint32Array(1);
|
93
|
+
libsdl.symbols.SDL_GetMouseState(ptr(xArr), ptr(yArr));
|
94
|
+
return {x: xArr[0], y: yArr[0]};
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
type buttons = 'left' | 'middle' | 'right';
|
99
|
+
|
100
|
+
export default Mouse;
|
package/src/slifer.ts
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
import { libimage, libsdl, libttf } from "./ffi";
|
2
|
+
import Global from "./global";
|
3
|
+
import { ptr } from 'bun:ffi';
|
4
|
+
import Graphics from "./modules/graphics";
|
5
|
+
import Keyboard from "./modules/keyboard";
|
6
|
+
import Mouse from "./modules/mouse";
|
7
|
+
|
8
|
+
export class SliferClass {
|
9
|
+
|
10
|
+
isRunning : boolean = true;
|
11
|
+
|
12
|
+
// Modules
|
13
|
+
Graphics = new Graphics();
|
14
|
+
Keyboard = new Keyboard();
|
15
|
+
Mouse = new Mouse();
|
16
|
+
|
17
|
+
constructor() {
|
18
|
+
const baseInit = libsdl.symbols.SDL_Init(0x00000020);
|
19
|
+
if (baseInit != 0) throw `SDL failed to initialize`;
|
20
|
+
|
21
|
+
const imageInit = libimage.symbols.IMG_Init(3);
|
22
|
+
if (imageInit != 3) throw `SDL Image failed to initialize`;
|
23
|
+
|
24
|
+
const ttfInit = libttf.symbols.TTF_Init();
|
25
|
+
if (ttfInit != 0) throw `SDL TTF failed to initialize`;
|
26
|
+
|
27
|
+
if (process.platform == "darwin") {
|
28
|
+
const tempFont = libttf.symbols.TTF_OpenFont(Buffer.from("/System/Library/Fonts/SFNSMono.ttf"), 12);
|
29
|
+
if (tempFont == null) throw `Default font loading failed`;
|
30
|
+
Global.ptrFont = tempFont;
|
31
|
+
}
|
32
|
+
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
*
|
37
|
+
* @param title Title of window
|
38
|
+
* @param width Width of window
|
39
|
+
* @param height Height of window
|
40
|
+
*/
|
41
|
+
createWindow(title: string, width: number, height: number) : void {
|
42
|
+
// Creating cstring buffer from string
|
43
|
+
const _title = Buffer.from(title + "\x00");
|
44
|
+
|
45
|
+
// Creating window pointer
|
46
|
+
const _win = libsdl.symbols.SDL_CreateWindow(_title, 0x2FFF0000, 0x2FFF0000, width, height, 0);
|
47
|
+
if (_win == null) throw `Window creation failed`;
|
48
|
+
Global.ptrWindow = _win;
|
49
|
+
|
50
|
+
// Creating renderer pointer
|
51
|
+
const _ren = libsdl.symbols.SDL_CreateRenderer(Global.ptrWindow, -1, 0);
|
52
|
+
if (_ren == null) throw `Renderer Creation failed`;
|
53
|
+
Global.ptrRenderer = _ren;
|
54
|
+
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
*
|
59
|
+
* @returns if the window should close
|
60
|
+
*/
|
61
|
+
shouldClose() : boolean {
|
62
|
+
|
63
|
+
// Clear the renderer
|
64
|
+
libsdl.symbols.SDL_RenderClear(Global.ptrRenderer);
|
65
|
+
|
66
|
+
// Poll Events
|
67
|
+
const eventArray = new Uint16Array(32);
|
68
|
+
const isEvent = libsdl.symbols.SDL_PollEvent(ptr(eventArray));
|
69
|
+
|
70
|
+
if (isEvent) {
|
71
|
+
switch (eventArray[0]) {
|
72
|
+
// Quit event
|
73
|
+
case 256:
|
74
|
+
this.isRunning = false;
|
75
|
+
break;
|
76
|
+
// Keydown event
|
77
|
+
case 768:
|
78
|
+
const _dscancode = eventArray[8];
|
79
|
+
const _dkey = libsdl.symbols.SDL_GetKeyFromScancode(_dscancode);
|
80
|
+
const _dname = libsdl.symbols.SDL_GetKeyName(_dkey);
|
81
|
+
Keyboard.setKeyDown(_dname.toString().toLowerCase());
|
82
|
+
break;
|
83
|
+
// Keyup event
|
84
|
+
case 769:
|
85
|
+
const _uscancode = eventArray[8];
|
86
|
+
const _ukey = libsdl.symbols.SDL_GetKeyFromScancode(_uscancode);
|
87
|
+
const _uname = libsdl.symbols.SDL_GetKeyName(_ukey);
|
88
|
+
Keyboard.setKeyUp(_uname.toString().toLowerCase());
|
89
|
+
break;
|
90
|
+
// Mouse down event
|
91
|
+
case 1025:
|
92
|
+
const _dbtn = eventArray[8] - 256;
|
93
|
+
Mouse.setButtonDown(_dbtn);
|
94
|
+
break;
|
95
|
+
// Mouse up event
|
96
|
+
case 1026:
|
97
|
+
const _ubtn = eventArray[8];
|
98
|
+
Mouse.setButtonUp(_ubtn);
|
99
|
+
break;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
return !this.isRunning;
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Slifers quit method
|
108
|
+
*/
|
109
|
+
quit() {
|
110
|
+
libttf.symbols.TTF_CloseFont(Global.ptrFont);
|
111
|
+
libsdl.symbols.SDL_DestroyRenderer(Global.ptrRenderer);
|
112
|
+
libsdl.symbols.SDL_DestroyWindow(Global.ptrWindow);
|
113
|
+
libsdl.symbols.SDL_Quit();
|
114
|
+
}
|
115
|
+
}
|
package/tsconfig.json
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
// Enable latest features
|
4
|
+
"lib": ["ESNext", "DOM"],
|
5
|
+
"target": "ESNext",
|
6
|
+
"module": "ESNext",
|
7
|
+
"moduleDetection": "force",
|
8
|
+
"jsx": "react-jsx",
|
9
|
+
"allowJs": true,
|
10
|
+
|
11
|
+
// Bundler mode
|
12
|
+
"moduleResolution": "bundler",
|
13
|
+
"allowImportingTsExtensions": true,
|
14
|
+
"verbatimModuleSyntax": true,
|
15
|
+
"noEmit": true,
|
16
|
+
|
17
|
+
// Best practices
|
18
|
+
"strict": true,
|
19
|
+
"skipLibCheck": true,
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
21
|
+
|
22
|
+
// Some stricter flags (disabled by default)
|
23
|
+
"noUnusedLocals": false,
|
24
|
+
"noUnusedParameters": false,
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
26
|
+
}
|
27
|
+
}
|