├── .gitignore
├── LICENSE
├── README.md
├── bin
└── steam_appid.txt
├── cbackend.go
├── docs
├── feature.png
├── go-inovation.wasm
├── index.html
└── wasm_exec.js
├── go.mod
├── go.sum
├── ino
├── fielddata.go
├── game.go
├── gamedata.go
├── icon.go
├── internal
│ ├── assets
│ │ ├── assets.go
│ │ ├── images
│ │ │ ├── color
│ │ │ │ ├── bg.png
│ │ │ │ ├── ino.png
│ │ │ │ ├── msg_en.png
│ │ │ │ ├── msg_ja.png
│ │ │ │ └── touch.png
│ │ │ ├── icons
│ │ │ │ ├── 16x16.png
│ │ │ │ ├── 32x32.png
│ │ │ │ └── 48x48.png
│ │ │ └── mono
│ │ │ │ ├── bg.png
│ │ │ │ ├── ino.png
│ │ │ │ └── msg.png
│ │ └── sound
│ │ │ ├── damage.wav
│ │ │ ├── heal.wav
│ │ │ ├── ino1.ogg
│ │ │ ├── ino2.ogg
│ │ │ ├── itemget.wav
│ │ │ ├── itemget2.wav
│ │ │ └── jump.wav
│ ├── audio
│ │ └── audio.go
│ ├── draw
│ │ └── draw.go
│ ├── field
│ │ └── field.go
│ ├── fieldtype
│ │ └── fieldtype.go
│ ├── font
│ │ ├── font.go
│ │ └── scaled.go
│ ├── input
│ │ ├── input.go
│ │ ├── touch_mobile.go
│ │ └── touch_notmobile.go
│ ├── lang
│ │ ├── lang_default.go
│ │ ├── lang_js.go
│ │ └── lang_steam.go
│ └── text
│ │ └── text.go
├── main.go
├── player.go
└── view.go
├── main.go
├── mobile
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── hajimehoshi
│ │ │ │ └── goinovation
│ │ │ │ ├── EbitenViewWithErrorHandling.java
│ │ │ │ └── MainActivity.java
│ │ │ └── res
│ │ │ ├── layout
│ │ │ └── activity_main.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── inovation
│ │ └── build.gradle
│ ├── mobile
│ │ └── build.gradle
│ └── settings.gradle
├── ios
│ ├── .gitignore
│ ├── goinovation.xcodeproj
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ └── goinovation
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── icon1024.png
│ │ │ ├── icon120-1.png
│ │ │ ├── icon120.png
│ │ │ ├── icon180.png
│ │ │ ├── icon58.png
│ │ │ ├── icon80.png
│ │ │ └── icon87.png
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── MobileEbitenViewControllerWithErrorHandling.h
│ │ ├── MobileEbitenViewControllerWithErrorHandling.m
│ │ └── main.m
└── mobile.go
├── notarize_app.sh
├── steam
├── community_capsule_184x69_english.png
├── community_capsule_184x69_japanese.png
├── icon
│ ├── icon_128x128.png
│ ├── icon_16x16.png
│ ├── icon_256x256.png
│ ├── icon_32x32.ico
│ ├── icon_32x32.png
│ ├── icon_512x512.icns
│ ├── icon_512x512.png
│ └── icon_64x64.png
├── library_capsule_600x900_english.png
├── library_capsule_600x900_japanese.png
├── library_hero_3840x1240_english.png
├── library_hero_3840x1240_japanese.png
├── library_logo_1280x720_english.png
├── library_logo_1280x720_japanese.png
├── msg_en.png
├── msg_ja.png
├── screenshot.png
├── screenshot
│ ├── convert.go
│ ├── screenshot3_1920x1080_english.png
│ ├── screenshot3_1920x1080_japanese.png
│ ├── screenshot3_english.png
│ ├── screenshot3_japanese.png
│ ├── screenshot4_1920x1080_english.png
│ ├── screenshot4_1920x1080_japanese.png
│ ├── screenshot4_english.png
│ ├── screenshot4_japanese.png
│ ├── screenshot5_1920x1080_english.png
│ ├── screenshot5_1920x1080_japanese.png
│ ├── screenshot5_english.png
│ ├── screenshot5_japanese.png
│ ├── screenshot6_1920x1080_english.png
│ ├── screenshot6_1920x1080_japanese.png
│ ├── screenshot6_english.png
│ ├── screenshot6_japanese.png
│ ├── screenshot7_1920x1080_english.png
│ ├── screenshot7_1920x1080_japanese.png
│ ├── screenshot7_english.png
│ └── screenshot7_japanese.png
├── store_header_capsule_460x215_english.png
├── store_header_capsule_460x215_japanese.png
├── store_main_capsule_616x353_english.png
├── store_main_capsule_616x353_japanese.png
├── store_small_capsule_231x87_english.png
├── store_small_capsule_231x87_japanese.png
├── store_vertical_capsule_374x448_english.png
├── store_vertical_capsule_374x448_japanese.png
├── title_en.png
└── title_ja.png
├── steambuild_darwin.sh
├── steambuild_linux.sh
├── steambuild_windows.sh
├── tools.go
└── zip_steambuilds.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .DS_Store
3 | *.framework
4 | *.xcframework
5 | *.aar
6 | *.jar
7 | bin/*
8 | !bin/steam_appid.txt
9 |
10 | # mobiles
11 | .idea
12 | mobile/android/app/release/
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Omega (The original auther)
2 | Copyright 2015 Haneda3 (JavaScript port)
3 | Copyright 2015 Hajime Hoshi (Go port)
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Go port of "Inovation 2007" by Omega
2 |
3 | ## Original Work
4 |
5 | http://o-mega.sakura.ne.jp/product/ino.html
6 |
7 | ## Releases
8 |
9 | ### Web Browsers
10 |
11 | http://hajimehoshi.github.io/go-inovation/
12 |
13 | ### Android
14 |
15 |
16 |
17 | ### iOS
18 |
19 |
20 |
21 | ### Privacy Policy
22 |
23 | We never collect any data from users in the above applications.
24 |
25 | ## How to install and run on desktops
26 |
27 | ```
28 | mkdir go-inovation
29 | cd go-inovation
30 | go mod init examle.com/m
31 | go run github.com/hajimehoshi/go-inovation
32 | ```
33 |
34 | ## How to build for Android
35 |
36 | ```
37 | git clone https://github.com/hajimehoshi/go-inovation
38 | cd go-inovation
39 | go run github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile bind -target android -javapkg com.hajimehoshi.goinovation -o ./mobile/android/inovation/inovation.aar ./mobile
40 | # You might need to specify Android SDK version like `-androidapi=23`
41 | ```
42 |
43 | and run the Android Studio project in `./mobile/android`.
44 |
45 | ## How to build for iOS
46 |
47 | ```
48 | git clone https://github.com/hajimehoshi/go-inovation
49 | cd go-inovation
50 | go run github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile bind -target ios -o ./mobile/ios/Mobile.xcframework ./mobile
51 | ```
52 |
53 | and run the Xcode project in `./mobile/ios`.
54 |
--------------------------------------------------------------------------------
/bin/steam_appid.txt:
--------------------------------------------------------------------------------
1 | 480
2 |
--------------------------------------------------------------------------------
/cbackend.go:
--------------------------------------------------------------------------------
1 | //go:build ebitencbackend
2 |
3 | package main
4 |
5 | import "C"
6 |
7 | //export GoMain
8 | func GoMain() {
9 | main()
10 | }
11 |
--------------------------------------------------------------------------------
/docs/feature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/docs/feature.png
--------------------------------------------------------------------------------
/docs/go-inovation.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/docs/go-inovation.wasm
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
26 |
Loading...
27 |
--------------------------------------------------------------------------------
/docs/wasm_exec.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | "use strict";
6 |
7 | (() => {
8 | const enosys = () => {
9 | const err = new Error("not implemented");
10 | err.code = "ENOSYS";
11 | return err;
12 | };
13 |
14 | if (!globalThis.fs) {
15 | let outputBuf = "";
16 | globalThis.fs = {
17 | constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
18 | writeSync(fd, buf) {
19 | outputBuf += decoder.decode(buf);
20 | const nl = outputBuf.lastIndexOf("\n");
21 | if (nl != -1) {
22 | console.log(outputBuf.substr(0, nl));
23 | outputBuf = outputBuf.substr(nl + 1);
24 | }
25 | return buf.length;
26 | },
27 | write(fd, buf, offset, length, position, callback) {
28 | if (offset !== 0 || length !== buf.length || position !== null) {
29 | callback(enosys());
30 | return;
31 | }
32 | const n = this.writeSync(fd, buf);
33 | callback(null, n);
34 | },
35 | chmod(path, mode, callback) { callback(enosys()); },
36 | chown(path, uid, gid, callback) { callback(enosys()); },
37 | close(fd, callback) { callback(enosys()); },
38 | fchmod(fd, mode, callback) { callback(enosys()); },
39 | fchown(fd, uid, gid, callback) { callback(enosys()); },
40 | fstat(fd, callback) { callback(enosys()); },
41 | fsync(fd, callback) { callback(null); },
42 | ftruncate(fd, length, callback) { callback(enosys()); },
43 | lchown(path, uid, gid, callback) { callback(enosys()); },
44 | link(path, link, callback) { callback(enosys()); },
45 | lstat(path, callback) { callback(enosys()); },
46 | mkdir(path, perm, callback) { callback(enosys()); },
47 | open(path, flags, mode, callback) { callback(enosys()); },
48 | read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
49 | readdir(path, callback) { callback(enosys()); },
50 | readlink(path, callback) { callback(enosys()); },
51 | rename(from, to, callback) { callback(enosys()); },
52 | rmdir(path, callback) { callback(enosys()); },
53 | stat(path, callback) { callback(enosys()); },
54 | symlink(path, link, callback) { callback(enosys()); },
55 | truncate(path, length, callback) { callback(enosys()); },
56 | unlink(path, callback) { callback(enosys()); },
57 | utimes(path, atime, mtime, callback) { callback(enosys()); },
58 | };
59 | }
60 |
61 | if (!globalThis.process) {
62 | globalThis.process = {
63 | getuid() { return -1; },
64 | getgid() { return -1; },
65 | geteuid() { return -1; },
66 | getegid() { return -1; },
67 | getgroups() { throw enosys(); },
68 | pid: -1,
69 | ppid: -1,
70 | umask() { throw enosys(); },
71 | cwd() { throw enosys(); },
72 | chdir() { throw enosys(); },
73 | }
74 | }
75 |
76 | if (!globalThis.crypto) {
77 | throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
78 | }
79 |
80 | if (!globalThis.performance) {
81 | throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");
82 | }
83 |
84 | if (!globalThis.TextEncoder) {
85 | throw new Error("globalThis.TextEncoder is not available, polyfill required");
86 | }
87 |
88 | if (!globalThis.TextDecoder) {
89 | throw new Error("globalThis.TextDecoder is not available, polyfill required");
90 | }
91 |
92 | const encoder = new TextEncoder("utf-8");
93 | const decoder = new TextDecoder("utf-8");
94 |
95 | globalThis.Go = class {
96 | constructor() {
97 | this.argv = ["js"];
98 | this.env = {};
99 | this.exit = (code) => {
100 | if (code !== 0) {
101 | console.warn("exit code:", code);
102 | }
103 | };
104 | this._exitPromise = new Promise((resolve) => {
105 | this._resolveExitPromise = resolve;
106 | });
107 | this._pendingEvent = null;
108 | this._scheduledTimeouts = new Map();
109 | this._nextCallbackTimeoutID = 1;
110 |
111 | const setInt64 = (addr, v) => {
112 | this.mem.setUint32(addr + 0, v, true);
113 | this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
114 | }
115 |
116 | const getInt64 = (addr) => {
117 | const low = this.mem.getUint32(addr + 0, true);
118 | const high = this.mem.getInt32(addr + 4, true);
119 | return low + high * 4294967296;
120 | }
121 |
122 | const loadValue = (addr) => {
123 | const f = this.mem.getFloat64(addr, true);
124 | if (f === 0) {
125 | return undefined;
126 | }
127 | if (!isNaN(f)) {
128 | return f;
129 | }
130 |
131 | const id = this.mem.getUint32(addr, true);
132 | return this._values[id];
133 | }
134 |
135 | const storeValue = (addr, v) => {
136 | const nanHead = 0x7FF80000;
137 |
138 | if (typeof v === "number" && v !== 0) {
139 | if (isNaN(v)) {
140 | this.mem.setUint32(addr + 4, nanHead, true);
141 | this.mem.setUint32(addr, 0, true);
142 | return;
143 | }
144 | this.mem.setFloat64(addr, v, true);
145 | return;
146 | }
147 |
148 | if (v === undefined) {
149 | this.mem.setFloat64(addr, 0, true);
150 | return;
151 | }
152 |
153 | let id = this._ids.get(v);
154 | if (id === undefined) {
155 | id = this._idPool.pop();
156 | if (id === undefined) {
157 | id = this._values.length;
158 | }
159 | this._values[id] = v;
160 | this._goRefCounts[id] = 0;
161 | this._ids.set(v, id);
162 | }
163 | this._goRefCounts[id]++;
164 | let typeFlag = 0;
165 | switch (typeof v) {
166 | case "object":
167 | if (v !== null) {
168 | typeFlag = 1;
169 | }
170 | break;
171 | case "string":
172 | typeFlag = 2;
173 | break;
174 | case "symbol":
175 | typeFlag = 3;
176 | break;
177 | case "function":
178 | typeFlag = 4;
179 | break;
180 | }
181 | this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
182 | this.mem.setUint32(addr, id, true);
183 | }
184 |
185 | const loadSlice = (addr) => {
186 | const array = getInt64(addr + 0);
187 | const len = getInt64(addr + 8);
188 | return new Uint8Array(this._inst.exports.mem.buffer, array, len);
189 | }
190 |
191 | const loadSliceOfValues = (addr) => {
192 | const array = getInt64(addr + 0);
193 | const len = getInt64(addr + 8);
194 | const a = new Array(len);
195 | for (let i = 0; i < len; i++) {
196 | a[i] = loadValue(array + i * 8);
197 | }
198 | return a;
199 | }
200 |
201 | const loadString = (addr) => {
202 | const saddr = getInt64(addr + 0);
203 | const len = getInt64(addr + 8);
204 | return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
205 | }
206 |
207 | const timeOrigin = Date.now() - performance.now();
208 | this.importObject = {
209 | go: {
210 | // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
211 | // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
212 | // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
213 | // This changes the SP, thus we have to update the SP used by the imported function.
214 |
215 | // func wasmExit(code int32)
216 | "runtime.wasmExit": (sp) => {
217 | sp >>>= 0;
218 | const code = this.mem.getInt32(sp + 8, true);
219 | this.exited = true;
220 | delete this._inst;
221 | delete this._values;
222 | delete this._goRefCounts;
223 | delete this._ids;
224 | delete this._idPool;
225 | this.exit(code);
226 | },
227 |
228 | // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
229 | "runtime.wasmWrite": (sp) => {
230 | sp >>>= 0;
231 | const fd = getInt64(sp + 8);
232 | const p = getInt64(sp + 16);
233 | const n = this.mem.getInt32(sp + 24, true);
234 | fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
235 | },
236 |
237 | // func resetMemoryDataView()
238 | "runtime.resetMemoryDataView": (sp) => {
239 | sp >>>= 0;
240 | this.mem = new DataView(this._inst.exports.mem.buffer);
241 | },
242 |
243 | // func nanotime1() int64
244 | "runtime.nanotime1": (sp) => {
245 | sp >>>= 0;
246 | setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
247 | },
248 |
249 | // func walltime() (sec int64, nsec int32)
250 | "runtime.walltime": (sp) => {
251 | sp >>>= 0;
252 | const msec = (new Date).getTime();
253 | setInt64(sp + 8, msec / 1000);
254 | this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
255 | },
256 |
257 | // func scheduleTimeoutEvent(delay int64) int32
258 | "runtime.scheduleTimeoutEvent": (sp) => {
259 | sp >>>= 0;
260 | const id = this._nextCallbackTimeoutID;
261 | this._nextCallbackTimeoutID++;
262 | this._scheduledTimeouts.set(id, setTimeout(
263 | () => {
264 | this._resume();
265 | while (this._scheduledTimeouts.has(id)) {
266 | // for some reason Go failed to register the timeout event, log and try again
267 | // (temporary workaround for https://github.com/golang/go/issues/28975)
268 | console.warn("scheduleTimeoutEvent: missed timeout event");
269 | this._resume();
270 | }
271 | },
272 | getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
273 | ));
274 | this.mem.setInt32(sp + 16, id, true);
275 | },
276 |
277 | // func clearTimeoutEvent(id int32)
278 | "runtime.clearTimeoutEvent": (sp) => {
279 | sp >>>= 0;
280 | const id = this.mem.getInt32(sp + 8, true);
281 | clearTimeout(this._scheduledTimeouts.get(id));
282 | this._scheduledTimeouts.delete(id);
283 | },
284 |
285 | // func getRandomData(r []byte)
286 | "runtime.getRandomData": (sp) => {
287 | sp >>>= 0;
288 | crypto.getRandomValues(loadSlice(sp + 8));
289 | },
290 |
291 | // func finalizeRef(v ref)
292 | "syscall/js.finalizeRef": (sp) => {
293 | sp >>>= 0;
294 | const id = this.mem.getUint32(sp + 8, true);
295 | this._goRefCounts[id]--;
296 | if (this._goRefCounts[id] === 0) {
297 | const v = this._values[id];
298 | this._values[id] = null;
299 | this._ids.delete(v);
300 | this._idPool.push(id);
301 | }
302 | },
303 |
304 | // func stringVal(value string) ref
305 | "syscall/js.stringVal": (sp) => {
306 | sp >>>= 0;
307 | storeValue(sp + 24, loadString(sp + 8));
308 | },
309 |
310 | // func valueGet(v ref, p string) ref
311 | "syscall/js.valueGet": (sp) => {
312 | sp >>>= 0;
313 | const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
314 | sp = this._inst.exports.getsp() >>> 0; // see comment above
315 | storeValue(sp + 32, result);
316 | },
317 |
318 | // func valueSet(v ref, p string, x ref)
319 | "syscall/js.valueSet": (sp) => {
320 | sp >>>= 0;
321 | Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
322 | },
323 |
324 | // func valueDelete(v ref, p string)
325 | "syscall/js.valueDelete": (sp) => {
326 | sp >>>= 0;
327 | Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
328 | },
329 |
330 | // func valueIndex(v ref, i int) ref
331 | "syscall/js.valueIndex": (sp) => {
332 | sp >>>= 0;
333 | storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
334 | },
335 |
336 | // valueSetIndex(v ref, i int, x ref)
337 | "syscall/js.valueSetIndex": (sp) => {
338 | sp >>>= 0;
339 | Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
340 | },
341 |
342 | // func valueCall(v ref, m string, args []ref) (ref, bool)
343 | "syscall/js.valueCall": (sp) => {
344 | sp >>>= 0;
345 | try {
346 | const v = loadValue(sp + 8);
347 | const m = Reflect.get(v, loadString(sp + 16));
348 | const args = loadSliceOfValues(sp + 32);
349 | const result = Reflect.apply(m, v, args);
350 | sp = this._inst.exports.getsp() >>> 0; // see comment above
351 | storeValue(sp + 56, result);
352 | this.mem.setUint8(sp + 64, 1);
353 | } catch (err) {
354 | sp = this._inst.exports.getsp() >>> 0; // see comment above
355 | storeValue(sp + 56, err);
356 | this.mem.setUint8(sp + 64, 0);
357 | }
358 | },
359 |
360 | // func valueInvoke(v ref, args []ref) (ref, bool)
361 | "syscall/js.valueInvoke": (sp) => {
362 | sp >>>= 0;
363 | try {
364 | const v = loadValue(sp + 8);
365 | const args = loadSliceOfValues(sp + 16);
366 | const result = Reflect.apply(v, undefined, args);
367 | sp = this._inst.exports.getsp() >>> 0; // see comment above
368 | storeValue(sp + 40, result);
369 | this.mem.setUint8(sp + 48, 1);
370 | } catch (err) {
371 | sp = this._inst.exports.getsp() >>> 0; // see comment above
372 | storeValue(sp + 40, err);
373 | this.mem.setUint8(sp + 48, 0);
374 | }
375 | },
376 |
377 | // func valueNew(v ref, args []ref) (ref, bool)
378 | "syscall/js.valueNew": (sp) => {
379 | sp >>>= 0;
380 | try {
381 | const v = loadValue(sp + 8);
382 | const args = loadSliceOfValues(sp + 16);
383 | const result = Reflect.construct(v, args);
384 | sp = this._inst.exports.getsp() >>> 0; // see comment above
385 | storeValue(sp + 40, result);
386 | this.mem.setUint8(sp + 48, 1);
387 | } catch (err) {
388 | sp = this._inst.exports.getsp() >>> 0; // see comment above
389 | storeValue(sp + 40, err);
390 | this.mem.setUint8(sp + 48, 0);
391 | }
392 | },
393 |
394 | // func valueLength(v ref) int
395 | "syscall/js.valueLength": (sp) => {
396 | sp >>>= 0;
397 | setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
398 | },
399 |
400 | // valuePrepareString(v ref) (ref, int)
401 | "syscall/js.valuePrepareString": (sp) => {
402 | sp >>>= 0;
403 | const str = encoder.encode(String(loadValue(sp + 8)));
404 | storeValue(sp + 16, str);
405 | setInt64(sp + 24, str.length);
406 | },
407 |
408 | // valueLoadString(v ref, b []byte)
409 | "syscall/js.valueLoadString": (sp) => {
410 | sp >>>= 0;
411 | const str = loadValue(sp + 8);
412 | loadSlice(sp + 16).set(str);
413 | },
414 |
415 | // func valueInstanceOf(v ref, t ref) bool
416 | "syscall/js.valueInstanceOf": (sp) => {
417 | sp >>>= 0;
418 | this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
419 | },
420 |
421 | // func copyBytesToGo(dst []byte, src ref) (int, bool)
422 | "syscall/js.copyBytesToGo": (sp) => {
423 | sp >>>= 0;
424 | const dst = loadSlice(sp + 8);
425 | const src = loadValue(sp + 32);
426 | if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
427 | this.mem.setUint8(sp + 48, 0);
428 | return;
429 | }
430 | const toCopy = src.subarray(0, dst.length);
431 | dst.set(toCopy);
432 | setInt64(sp + 40, toCopy.length);
433 | this.mem.setUint8(sp + 48, 1);
434 | },
435 |
436 | // func copyBytesToJS(dst ref, src []byte) (int, bool)
437 | "syscall/js.copyBytesToJS": (sp) => {
438 | sp >>>= 0;
439 | const dst = loadValue(sp + 8);
440 | const src = loadSlice(sp + 16);
441 | if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
442 | this.mem.setUint8(sp + 48, 0);
443 | return;
444 | }
445 | const toCopy = src.subarray(0, dst.length);
446 | dst.set(toCopy);
447 | setInt64(sp + 40, toCopy.length);
448 | this.mem.setUint8(sp + 48, 1);
449 | },
450 |
451 | "debug": (value) => {
452 | console.log(value);
453 | },
454 | }
455 | };
456 | }
457 |
458 | async run(instance) {
459 | if (!(instance instanceof WebAssembly.Instance)) {
460 | throw new Error("Go.run: WebAssembly.Instance expected");
461 | }
462 | this._inst = instance;
463 | this.mem = new DataView(this._inst.exports.mem.buffer);
464 | this._values = [ // JS values that Go currently has references to, indexed by reference id
465 | NaN,
466 | 0,
467 | null,
468 | true,
469 | false,
470 | globalThis,
471 | this,
472 | ];
473 | this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
474 | this._ids = new Map([ // mapping from JS values to reference ids
475 | [0, 1],
476 | [null, 2],
477 | [true, 3],
478 | [false, 4],
479 | [globalThis, 5],
480 | [this, 6],
481 | ]);
482 | this._idPool = []; // unused ids that have been garbage collected
483 | this.exited = false; // whether the Go program has exited
484 |
485 | // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
486 | let offset = 4096;
487 |
488 | const strPtr = (str) => {
489 | const ptr = offset;
490 | const bytes = encoder.encode(str + "\0");
491 | new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
492 | offset += bytes.length;
493 | if (offset % 8 !== 0) {
494 | offset += 8 - (offset % 8);
495 | }
496 | return ptr;
497 | };
498 |
499 | const argc = this.argv.length;
500 |
501 | const argvPtrs = [];
502 | this.argv.forEach((arg) => {
503 | argvPtrs.push(strPtr(arg));
504 | });
505 | argvPtrs.push(0);
506 |
507 | const keys = Object.keys(this.env).sort();
508 | keys.forEach((key) => {
509 | argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
510 | });
511 | argvPtrs.push(0);
512 |
513 | const argv = offset;
514 | argvPtrs.forEach((ptr) => {
515 | this.mem.setUint32(offset, ptr, true);
516 | this.mem.setUint32(offset + 4, 0, true);
517 | offset += 8;
518 | });
519 |
520 | // The linker guarantees global data starts from at least wasmMinDataAddr.
521 | // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
522 | const wasmMinDataAddr = 4096 + 8192;
523 | if (offset >= wasmMinDataAddr) {
524 | throw new Error("total length of command line and environment variables exceeds limit");
525 | }
526 |
527 | this._inst.exports.run(argc, argv);
528 | if (this.exited) {
529 | this._resolveExitPromise();
530 | }
531 | await this._exitPromise;
532 | }
533 |
534 | _resume() {
535 | if (this.exited) {
536 | throw new Error("Go program has already exited");
537 | }
538 | this._inst.exports.resume();
539 | if (this.exited) {
540 | this._resolveExitPromise();
541 | }
542 | }
543 |
544 | _makeFuncWrapper(id) {
545 | const go = this;
546 | return function () {
547 | const event = { id: id, this: this, args: arguments };
548 | go._pendingEvent = event;
549 | go._resume();
550 | return event.result;
551 | };
552 | }
553 | }
554 | })();
555 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/hajimehoshi/go-inovation
2 |
3 | go 1.23.0
4 |
5 | require (
6 | github.com/hajimehoshi/bitmapfont/v3 v3.2.1
7 | github.com/hajimehoshi/ebiten/v2 v2.8.7
8 | github.com/hajimehoshi/go-steamworks v0.0.0-20241112125913-96b2a6baef69
9 | golang.org/x/image v0.26.0
10 | golang.org/x/text v0.24.0
11 | )
12 |
13 | require (
14 | github.com/ebitengine/gomobile v0.0.0-20250329061421-6d0a8e981e4c // indirect
15 | github.com/ebitengine/hideconsole v1.0.0 // indirect
16 | github.com/ebitengine/oto/v3 v3.4.0-alpha.7 // indirect
17 | github.com/ebitengine/purego v0.9.0-alpha.3 // indirect
18 | github.com/go-text/typesetting v0.3.0 // indirect
19 | github.com/jezek/xgb v1.1.1 // indirect
20 | github.com/jfreymuth/oggvorbis v1.0.5 // indirect
21 | github.com/jfreymuth/vorbis v1.0.2 // indirect
22 | github.com/pierrec/lz4/v4 v4.1.21 // indirect
23 | golang.org/x/mod v0.24.0 // indirect
24 | golang.org/x/sync v0.13.0 // indirect
25 | golang.org/x/sys v0.32.0 // indirect
26 | golang.org/x/tools v0.32.0 // indirect
27 | )
28 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/ebitengine/gomobile v0.0.0-20250329061421-6d0a8e981e4c h1:Ccgks2VROTr6bIm1FFxG2jT6P1DaCBMj8g/O9xbOQ08=
2 | github.com/ebitengine/gomobile v0.0.0-20250329061421-6d0a8e981e4c/go.mod h1:M6DDA2RbegvWBVv4Dq482lwyFTtMczT1A7UNm1qOYzY=
3 | github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
4 | github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A=
5 | github.com/ebitengine/oto/v3 v3.4.0-alpha.7 h1:0rd2hzmixykApKPnLn0x39UWV3+mu/iNzfZ8YJfJBW8=
6 | github.com/ebitengine/oto/v3 v3.4.0-alpha.7/go.mod h1:poYRm0BcahJ49XN646C6Yg7wMc0gcwQNiC5ASQDCNnU=
7 | github.com/ebitengine/purego v0.9.0-alpha.3 h1:5kv5zzhJYYLOYAdA/ZBMt+L89cG2B3cNyYWeDgFw73I=
8 | github.com/ebitengine/purego v0.9.0-alpha.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
9 | github.com/go-text/typesetting v0.3.0 h1:OWCgYpp8njoxSRpwrdd1bQOxdjOXDj9Rqart9ML4iF4=
10 | github.com/go-text/typesetting v0.3.0/go.mod h1:qjZLkhRgOEYMhU9eHBr3AR4sfnGJvOXNLt8yRAySFuY=
11 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
12 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
13 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
14 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
15 | github.com/hajimehoshi/bitmapfont/v3 v3.2.1 h1:33Lw85DZolX3upouUqf6Qza8HYGIROvr7SYin7PzIZ8=
16 | github.com/hajimehoshi/bitmapfont/v3 v3.2.1/go.mod h1:8gLqGatKVu0pwcNCJguW3Igg9WQqVXF0zg/RvrGQWyg=
17 | github.com/hajimehoshi/ebiten/v2 v2.8.7 h1:DnvNZuB8RF0ffOUTuqaXHl9d51VAT9XYfEMQPYD37v4=
18 | github.com/hajimehoshi/ebiten/v2 v2.8.7/go.mod h1:durJ05+OYnio9b8q0sEtOgaNeBEQG7Yr7lRviAciYbs=
19 | github.com/hajimehoshi/go-steamworks v0.0.0-20241112125913-96b2a6baef69 h1:R5DmT3Ffuccaf3U7DiLYpro2avyBz7D112v9eqm8NvE=
20 | github.com/hajimehoshi/go-steamworks v0.0.0-20241112125913-96b2a6baef69/go.mod h1:xQbwn4VSK2CwjfAgpolFH8MYSu96NQZhiOuksu1vvdY=
21 | github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
22 | github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
23 | github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ=
24 | github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
25 | github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
26 | github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
27 | github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
28 | github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
29 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
30 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
31 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
32 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
33 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
34 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
35 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
36 | golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
37 | golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
38 | golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
39 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
40 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
41 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
42 | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
43 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
44 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
45 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
46 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
47 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
48 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
49 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
50 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
51 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
52 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
53 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
54 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
55 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
56 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
57 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
58 | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
59 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
60 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
61 | golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
62 | golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
63 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
64 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
65 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
66 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
67 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
68 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
69 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
70 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
71 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
72 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
73 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
74 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
75 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
76 | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
77 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
78 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
79 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
80 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
81 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
82 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
83 | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
84 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
85 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
86 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
87 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
88 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
89 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
90 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
91 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
92 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
93 | golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
94 | golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
95 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
96 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
97 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
98 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
99 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
100 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
101 | golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
102 | golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
103 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
104 |
--------------------------------------------------------------------------------
/ino/fielddata.go:
--------------------------------------------------------------------------------
1 | package ino
2 |
3 | var field_data = `
4 | UUUU UUUUUUUUUUUUUUUUUUUBBB
5 | UL U U B BBBBBBBB
6 | U U UUUUUUUUUUUBBBBBHH PB UUUUUUUUUUUUUUU B B
7 | U UUUUUUU BB H UUUUUUUUUUUUUUUBBB UU U B p B
8 | UU B lBUU UU UUUUUUB BBBB B
9 | UU BBBBBBBB BBBBBBBBBBBBBB UUUU BBBBBBBBB H B hB B
10 | UUUU BBBBHHBB BB UUUU Br BB UBUB B B
11 | U B H ~~~ B U BBU BBBBUUUU* B~~B *
12 | U UB B B U BB UU BB B B B B
13 | U UB B a ~~~~ B UU B UUUBBB B B~~B B
14 | U UUB BBBB BUUUUUUUUUUUUU BBB U BB B B B B BBBBBBBBBBBB
15 | U UUB ~~~~~ B BBB UU BBBB B B~~B B B B
16 | U UUUB ~~~~ H BBUUUU BBB * B B * B B
17 | UU B ~~~~ BBBBBBBBBBBBBBBBB U BB B B~~B B B B
18 | U Bz ~~~~ ~ g UUU dB B B B B B B B
19 | UU B~~~~ @ BBBBBBBBBBBBBB~ BBBBBB~~B B B B B
20 | U B B **B~BBBB B BBBBBBBBBBBB b B B
21 | UU BBBBBBBBBBBBBBBBBBBBBBHB**B U BBBBB~ ~~~~~~~~~ ~~~~~~~~~~~B~ BBB* *
22 | U U B U B BBBHHBBBBBBBBBBBBBBBBBBB~ B * *
23 | UUUUUUUBBBBBBBBBBBBBBBBBBBBBBBBHHBBBBBB BB BBB UUHU BB B * *
24 | U BB U U Bj BBBBB BBBBB U U BBB B * *
25 | UU HH fU U BBB BBBB B U U B B * *
26 | U UBUUUUU UUUUUUUUUUUUU BB U B BB * *
27 | U UB ~~ ~~ ~~ <<<<<< <<<<<<<<<<<<<<<<<<< U*UU B BBB * *
28 | U UUB~ ~~ ~~ B B B o B B * *
29 | UU B ~~ ~~ ~~ B >>>>>>> BB BBBBBBBBBBBBBBBBBBBBB BB B * *
30 | UU B~~~ ~~~ ~~~ B BBBBBBBBB BBHBBBBBBBBBBBBB BHBBBBBBBB B * L*
31 | UUU B ~~~ ~~~ ~~~ B B * e U B B * *
32 | UUU UB~~~i ~~~ ~~~ ~~~ B B IIIIIBBB U B BB * *
33 | UU UB* ~~~ ~~~ ~~~ ~~~ BBB IIIII B B BBB * *
34 | U UUBHHBBBB<<<<<>>>>>BBBBB >>>>>>>> B B B * *
35 | U U BBBBBBBBBB~ B B B nB<<<~B * *
36 | U UUU UU B ~~ BBB ~~ P B BBB B * *
37 | U~UUUUU B ~~B k B~~ BBB BBBB B~>>>B * *
38 | U UUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU B BBBBBBBBB BBB B B * *
39 | U~ U U B~ *** BBB~~~~B * *
40 | B UUUUU U H~~B~ c B~~B * * *
41 | B~~U UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUBBBBBBBBBBBBBBBB*BBBBBBBBBBBBBB~~BBBBBBBBB>>>>>>IIIIIIIIII * *
42 | B B BBB U B B * *
43 | B~~BB U B<<<<<<<<~B BBBBBBBBBB B
44 | B B* m U B B B B
45 | B~~BIIIII U B~>>>>>>>>B H B
46 | B B > U B B H BU
47 | B~~B < < BBBBB U B<<<<<<<<~B B HUUUUU
48 | B B <<<<<< BBBB~B B B B B H U
49 | B~~B BBB B B~>>>>>>>>BBHHHHHHHBB H U
50 | B B ~BBBBB B B q BU U
51 | B~~B B BBB BUUUUUUUUBBBIIIIIII IIIIIIII<<= fieldtype.FIELD_ITEM_BORDER &&
77 | f.field[y*maxFieldX+x] != fieldtype.FIELD_ITEM_STARTPOINT
78 | }
79 |
80 | func (f *Field) IsItemGettable(x, y int, gameData GameData) bool {
81 | if !f.IsItem(x, y) {
82 | return false
83 | }
84 | if f.field[y*maxFieldX+x] == fieldtype.FIELD_ITEM_OMEGA && gameData.IsHiddenSecret() {
85 | return false
86 | }
87 | return true
88 | }
89 |
90 | func (f *Field) EraseField(x, y int) {
91 | f.field[y*maxFieldX+x] = fieldtype.FIELD_NONE
92 | }
93 |
94 | type GameData interface {
95 | IsHiddenSecret() bool
96 | }
97 |
98 | func (f *Field) Draw(screen *ebiten.Image, gameData GameData, viewPositionX, viewPositionY int) {
99 | const (
100 | graphicOffsetX = -16 - 16*2
101 | graphicOffsetY = 8 - 16*2
102 | )
103 | vx, vy := viewPositionX, viewPositionY
104 | ofs_x := CHAR_SIZE - vx%CHAR_SIZE
105 | ofs_y := CHAR_SIZE - vy%CHAR_SIZE
106 | for xx := -(draw.ScreenWidth/CHAR_SIZE/2 + 2); xx < (draw.ScreenWidth/CHAR_SIZE/2 + 2); xx++ {
107 | fx := xx + vx/CHAR_SIZE
108 | if fx < 0 || fx >= maxFieldX {
109 | continue
110 | }
111 | for yy := -(draw.ScreenHeight/CHAR_SIZE/2 + 2); yy < (draw.ScreenHeight/CHAR_SIZE/2 + 2); yy++ {
112 | fy := yy + vy/CHAR_SIZE
113 | if fy < 0 || fy >= maxFieldY {
114 | continue
115 | }
116 |
117 | gy := (f.timer / 10) % 4
118 | gx := int(f.field[fy*maxFieldX+fx])
119 |
120 | if f.IsItem(fx, fy) {
121 | gx -= (int(fieldtype.FIELD_ITEM_BORDER) + 1)
122 | gy = 4 + gx/16
123 | gx = gx % 16
124 | }
125 |
126 | if gameData.IsHiddenSecret() && f.field[fy*maxFieldX+fx] == fieldtype.FIELD_ITEM_OMEGA {
127 | continue
128 | }
129 |
130 | draw.Draw(screen, "ino",
131 | (xx+12)*CHAR_SIZE+ofs_x+graphicOffsetX+(draw.ScreenWidth-320)/2,
132 | (yy+8)*CHAR_SIZE+ofs_y+graphicOffsetY+(draw.ScreenHeight-240)/2,
133 | gx*16, gy*16, 16, 16)
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/ino/internal/fieldtype/fieldtype.go:
--------------------------------------------------------------------------------
1 | package fieldtype
2 |
3 | import (
4 | "golang.org/x/text/language"
5 |
6 | "github.com/hajimehoshi/go-inovation/ino/internal/text"
7 | )
8 |
9 | type FieldType int
10 |
11 | const (
12 | FIELD_NONE FieldType = iota // なし
13 | FIELD_HIDEPATH // 隠しルート(見えるけど判定のないブロック)
14 | FIELD_UNVISIBLE // 不可視ブロック(見えないけど判定があるブロック)
15 | FIELD_BLOCK // 通常ブロック
16 | FIELD_BAR // 床。降りたり上ったりできる
17 | FIELD_SCROLL_L // ベルト床左
18 | FIELD_SCROLL_R // ベルト床右
19 | FIELD_SPIKE // トゲ
20 | FIELD_SLIP // すべる
21 | FIELD_ITEM_BORDER // アイテムチェック用
22 | FIELD_ITEM_POWERUP // パワーアップ
23 | // ふじ系
24 | FIELD_ITEM_FUJI
25 | FIELD_ITEM_BUSHI
26 | FIELD_ITEM_APPLE
27 | FIELD_ITEM_V
28 | // たか系
29 | FIELD_ITEM_TAKA
30 | FIELD_ITEM_SHUOLDER
31 | FIELD_ITEM_DAGGER
32 | FIELD_ITEM_KATAKATA
33 | // なす系
34 | FIELD_ITEM_NASU
35 | FIELD_ITEM_BONUS
36 | FIELD_ITEM_NURSE
37 | FIELD_ITEM_NAZUNA
38 | // くそげー系
39 | FIELD_ITEM_GAMEHELL
40 | FIELD_ITEM_GUNDAM
41 | FIELD_ITEM_POED
42 | FIELD_ITEM_MILESTONE
43 | FIELD_ITEM_1YEN
44 | FIELD_ITEM_TRIANGLE
45 | FIELD_ITEM_OMEGA // 隠し
46 | FIELD_ITEM_LIFE // ハート
47 | FIELD_ITEM_STARTPOINT // 開始地点
48 | FIELD_ITEM_MAX
49 | )
50 |
51 | func (f FieldType) ItemMessage(lang language.Tag) string {
52 | return text.Get(lang, text.TextID(f-FIELD_ITEM_POWERUP)+text.TextIDItemPowerUp)
53 | }
54 |
--------------------------------------------------------------------------------
/ino/internal/font/font.go:
--------------------------------------------------------------------------------
1 | package font
2 |
3 | import (
4 | "image/color"
5 | "strings"
6 |
7 | "github.com/hajimehoshi/bitmapfont/v3"
8 | "github.com/hajimehoshi/ebiten/v2"
9 | "github.com/hajimehoshi/ebiten/v2/text/v2"
10 | "golang.org/x/image/font"
11 | "golang.org/x/image/math/fixed"
12 | )
13 |
14 | const LineHeight = 16
15 |
16 | func tokens(str string) []string {
17 | tokens := []string{}
18 | for {
19 | var strs []string
20 | switch len(tokens) % 2 {
21 | case 0:
22 | strs = strings.SplitN(str, "", 2)
23 | case 1:
24 | strs = strings.SplitN(str, "", 2)
25 | }
26 | if len(strs) >= 1 {
27 | tokens = append(tokens, strs[0])
28 | }
29 | if len(strs) == 2 {
30 | str = strs[1]
31 | } else {
32 | break
33 | }
34 | }
35 | return tokens
36 | }
37 |
38 | func Width(str string) int {
39 | w := fixed.I(0)
40 | for _, t := range tokens(str) {
41 | w += font.MeasureString(bitmapfont.Face, t)
42 | }
43 | return w.Round()
44 | }
45 |
46 | func Height(str string) int {
47 | return (strings.Count(str, "\n") + 1) * LineHeight
48 | }
49 |
50 | var red = color.RGBA{0xe4, 0x32, 0x60, 0xff}
51 |
52 | var face = text.NewGoXFace(bitmapfont.Face)
53 |
54 | func DrawText(target *ebiten.Image, str string, x, y int, clr color.Color) {
55 | xf := float64(x)
56 | yf := float64(y)
57 | for i, t := range tokens(str) {
58 | clr := clr
59 | if i%2 == 1 {
60 | clr = red
61 | }
62 | op := &text.DrawOptions{}
63 | op.GeoM.Translate(xf, yf)
64 | op.ColorScale.ScaleWithColor(clr)
65 | text.Draw(target, t, face, op)
66 | xf += text.Advance(t, face)
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ino/internal/font/scaled.go:
--------------------------------------------------------------------------------
1 | package font
2 |
3 | import (
4 | "image"
5 | "image/color"
6 |
7 | "golang.org/x/image/font"
8 | "golang.org/x/image/math/fixed"
9 | )
10 |
11 | type scaledImage struct {
12 | image image.Image
13 | scale int
14 | }
15 |
16 | func (s *scaledImage) ColorModel() color.Model {
17 | return s.image.ColorModel()
18 | }
19 |
20 | func (s *scaledImage) Bounds() image.Rectangle {
21 | b := s.image.Bounds()
22 | b.Min = b.Min.Mul(s.scale)
23 | b.Max = b.Max.Mul(s.scale)
24 | return b
25 | }
26 |
27 | func euclidianDiv(x, y int) int {
28 | if x < 0 {
29 | x -= y - 1
30 | }
31 | return x / y
32 | }
33 |
34 | func (s *scaledImage) At(x, y int) color.Color {
35 | x = euclidianDiv(x, s.scale)
36 | y = euclidianDiv(y, s.scale)
37 | return s.image.At(x, y)
38 | }
39 |
40 | func scaleFont(f font.Face, scale int) font.Face {
41 | if scale == 1 {
42 | return f
43 | }
44 | return &scaled{f, scale}
45 | }
46 |
47 | type scaled struct {
48 | font font.Face
49 | scale int
50 | }
51 |
52 | func (s *scaled) Close() error {
53 | return s.font.Close()
54 | }
55 |
56 | func (s *scaled) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
57 | dr, mask, maskp, advance, ok = s.font.Glyph(dot, r)
58 | if !ok {
59 | return
60 | }
61 | d := image.Pt(dot.X.Floor(), dot.Y.Floor())
62 | dr.Min = dr.Min.Sub(d).Mul(s.scale).Add(d)
63 | dr.Max = dr.Max.Sub(d).Mul(s.scale).Add(d)
64 | maskp = maskp.Mul(s.scale)
65 | advance *= fixed.Int26_6(s.scale)
66 | return dr, &scaledImage{mask, s.scale}, maskp, advance, ok
67 | }
68 |
69 | func (s *scaled) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
70 | bounds, advance, ok = s.font.GlyphBounds(r)
71 | if !ok {
72 | return
73 | }
74 | bounds.Min.X *= fixed.Int26_6(s.scale)
75 | bounds.Min.Y *= fixed.Int26_6(s.scale)
76 | bounds.Max.X *= fixed.Int26_6(s.scale)
77 | bounds.Max.Y *= fixed.Int26_6(s.scale)
78 | advance *= fixed.Int26_6(s.scale)
79 | return
80 | }
81 |
82 | func (s *scaled) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
83 | advance, ok = s.font.GlyphAdvance(r)
84 | if !ok {
85 | return
86 | }
87 | advance *= fixed.Int26_6(s.scale)
88 | return
89 | }
90 |
91 | func (s *scaled) Kern(r0, r1 rune) fixed.Int26_6 {
92 | return s.font.Kern(r0, r1) * fixed.Int26_6(s.scale)
93 | }
94 |
95 | func (s *scaled) Metrics() font.Metrics {
96 | m := s.font.Metrics()
97 | return font.Metrics{
98 | Height: m.Height * fixed.Int26_6(s.scale),
99 | Ascent: m.Ascent * fixed.Int26_6(s.scale),
100 | Descent: m.Descent * fixed.Int26_6(s.scale),
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/ino/internal/input/input.go:
--------------------------------------------------------------------------------
1 | package input
2 |
3 | import (
4 | "github.com/hajimehoshi/ebiten/v2"
5 | "github.com/hajimehoshi/ebiten/v2/inpututil"
6 | )
7 |
8 | const (
9 | // TODO: This is duplicated with draw package's definitions.
10 | ScreenWidth = 320
11 | ScreenHeight = 240
12 | )
13 |
14 | var theInput = &Input{
15 | pressed: map[ebiten.Key]struct{}{},
16 | prevPressed: map[ebiten.Key]struct{}{},
17 | }
18 |
19 | func Current() *Input {
20 | return theInput
21 | }
22 |
23 | type Direction int
24 |
25 | const (
26 | DirectionLeft Direction = iota
27 | DirectionRight
28 | DirectionDown
29 | )
30 |
31 | var keys = []ebiten.Key{
32 | ebiten.KeyEnter,
33 | ebiten.KeySpace,
34 | ebiten.KeyLeft,
35 | ebiten.KeyDown,
36 | ebiten.KeyRight,
37 |
38 | // Fullscreen
39 | ebiten.KeyF,
40 |
41 | // Profiling
42 | ebiten.KeyP,
43 | ebiten.KeyQ,
44 | }
45 |
46 | type Input struct {
47 | pressed map[ebiten.Key]struct{}
48 | prevPressed map[ebiten.Key]struct{}
49 | touchMode bool
50 |
51 | gamepadID ebiten.GamepadID
52 | gamepadEnabled bool
53 | }
54 |
55 | func (i *Input) IsTouchEnabled() bool {
56 | if isTouchPrimaryInput() {
57 | return true
58 | }
59 | return i.touchMode
60 | }
61 |
62 | func (i *Input) Update() {
63 | i.prevPressed = map[ebiten.Key]struct{}{}
64 | for k := range i.pressed {
65 | i.prevPressed[k] = struct{}{}
66 | }
67 | i.pressed = map[ebiten.Key]struct{}{}
68 | for _, k := range keys {
69 | if ebiten.IsKeyPressed(k) {
70 | i.pressed[k] = struct{}{}
71 | }
72 | }
73 |
74 | // Emulates the keys by gamepad pressing
75 | gamepadIDs := ebiten.GamepadIDs()
76 | if len(gamepadIDs) > 0 {
77 | if !i.gamepadEnabled {
78 | i.gamepadID = gamepadIDs[0]
79 | i.gamepadEnabled = true
80 | } else {
81 | var found bool
82 | for _, id := range gamepadIDs {
83 | if i.gamepadID == id {
84 | found = true
85 | break
86 | }
87 | }
88 | if !found {
89 | i.gamepadID = gamepadIDs[0]
90 | }
91 | }
92 | } else {
93 | i.gamepadEnabled = false
94 | }
95 |
96 | var gamepadUsed bool
97 | if i.gamepadEnabled {
98 | const threshold = 0.8
99 | var x, y float64
100 | std := ebiten.IsStandardGamepadLayoutAvailable(i.gamepadID)
101 | if std {
102 | x = ebiten.StandardGamepadAxisValue(i.gamepadID, ebiten.StandardGamepadAxisLeftStickHorizontal)
103 | y = ebiten.StandardGamepadAxisValue(i.gamepadID, ebiten.StandardGamepadAxisLeftStickVertical)
104 |
105 | switch {
106 | case ebiten.IsStandardGamepadButtonPressed(i.gamepadID, ebiten.StandardGamepadButtonLeftLeft):
107 | x = -1
108 | case ebiten.IsStandardGamepadButtonPressed(i.gamepadID, ebiten.StandardGamepadButtonLeftRight):
109 | x = 1
110 | case ebiten.IsStandardGamepadButtonPressed(i.gamepadID, ebiten.StandardGamepadButtonLeftBottom):
111 | y = 1
112 | }
113 | } else {
114 | x = ebiten.GamepadAxis(i.gamepadID, 0)
115 | y = ebiten.GamepadAxis(i.gamepadID, 1)
116 | }
117 | switch {
118 | case -threshold >= x:
119 | i.pressed[ebiten.KeyLeft] = struct{}{}
120 | gamepadUsed = true
121 | case threshold <= x:
122 | i.pressed[ebiten.KeyRight] = struct{}{}
123 | gamepadUsed = true
124 | }
125 | if y >= threshold {
126 | i.pressed[ebiten.KeyDown] = struct{}{}
127 | gamepadUsed = true
128 | }
129 |
130 | if std {
131 | if ebiten.IsStandardGamepadButtonPressed(i.gamepadID, ebiten.StandardGamepadButtonRightBottom) ||
132 | ebiten.IsStandardGamepadButtonPressed(i.gamepadID, ebiten.StandardGamepadButtonRightRight) {
133 | i.pressed[ebiten.KeyEnter] = struct{}{}
134 | i.pressed[ebiten.KeySpace] = struct{}{}
135 | gamepadUsed = true
136 | }
137 | } else {
138 | for b := ebiten.GamepadButton0; b <= ebiten.GamepadButton3; b++ {
139 | if ebiten.IsGamepadButtonPressed(i.gamepadID, b) {
140 | i.pressed[ebiten.KeyEnter] = struct{}{}
141 | i.pressed[ebiten.KeySpace] = struct{}{}
142 | gamepadUsed = true
143 | break
144 | }
145 | }
146 | }
147 | }
148 |
149 | // Emulates the keys by touching
150 | touches := ebiten.TouchIDs()
151 | for _, t := range touches {
152 | x, y := ebiten.TouchPosition(t)
153 | // TODO(hajimehoshi): 64 are magic numbers
154 | if y < ScreenHeight-64 {
155 | continue
156 | }
157 | switch {
158 | case ScreenWidth <= x:
159 | case ScreenWidth*3/4 <= x:
160 | i.pressed[ebiten.KeyEnter] = struct{}{}
161 | i.pressed[ebiten.KeySpace] = struct{}{}
162 | case ScreenWidth*2/4 <= x:
163 | i.pressed[ebiten.KeyDown] = struct{}{}
164 | case ScreenWidth/4 <= x:
165 | i.pressed[ebiten.KeyRight] = struct{}{}
166 | default:
167 | i.pressed[ebiten.KeyLeft] = struct{}{}
168 | }
169 | }
170 |
171 | if 0 < len(touches) {
172 | i.touchMode = true
173 | } else if gamepadUsed {
174 | i.touchMode = false
175 | }
176 | }
177 |
178 | func inLanguageSwitcher(x, y int) bool {
179 | return ScreenWidth*3/4 <= x && y < ScreenHeight/4
180 | }
181 |
182 | func (i *Input) IsSpaceTouched() bool {
183 | for _, t := range ebiten.TouchIDs() {
184 | x, y := ebiten.TouchPosition(t)
185 | if !inLanguageSwitcher(x, y) && y < ScreenHeight-64 {
186 | return true
187 | }
188 | }
189 | return false
190 | }
191 |
192 | func (i *Input) IsSpaceJustTouched() bool {
193 | for _, t := range inpututil.JustPressedTouchIDs() {
194 | x, y := ebiten.TouchPosition(t)
195 | if !inLanguageSwitcher(x, y) && y < ScreenHeight-64 {
196 | return true
197 | }
198 | }
199 | return false
200 | }
201 |
202 | func (i *Input) IsKeyPressed(key ebiten.Key) bool {
203 | _, ok := i.pressed[key]
204 | return ok
205 | }
206 |
207 | func (i *Input) IsKeyJustPressed(key ebiten.Key) bool {
208 | _, ok := i.pressed[key]
209 | if !ok {
210 | return false
211 | }
212 | _, ok = i.prevPressed[key]
213 | return !ok
214 | }
215 |
216 | func (i *Input) IsActionKeyPressed() bool {
217 | return i.IsKeyPressed(ebiten.KeyEnter) || i.IsKeyPressed(ebiten.KeySpace)
218 | }
219 |
220 | func (i *Input) IsActionKeyJustPressed() bool {
221 | return i.IsKeyJustPressed(ebiten.KeyEnter) || i.IsKeyJustPressed(ebiten.KeySpace)
222 | }
223 |
224 | func (i *Input) IsDirectionKeyPressed(dir Direction) bool {
225 | switch dir {
226 | case DirectionLeft:
227 | return i.IsKeyPressed(ebiten.KeyLeft)
228 | case DirectionRight:
229 | return i.IsKeyPressed(ebiten.KeyRight)
230 | case DirectionDown:
231 | return i.IsKeyPressed(ebiten.KeyDown)
232 | default:
233 | panic("not reach")
234 | }
235 | }
236 |
237 | func (i *Input) IsLanguageSwitcherPressed() bool {
238 | if inpututil.IsKeyJustPressed(ebiten.KeyL) {
239 | return true
240 | }
241 | if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
242 | if inLanguageSwitcher(ebiten.CursorPosition()) {
243 | return true
244 | }
245 | }
246 | for _, t := range inpututil.JustPressedTouchIDs() {
247 | if inLanguageSwitcher(ebiten.TouchPosition(t)) {
248 | return true
249 | }
250 | }
251 | return false
252 | }
253 |
--------------------------------------------------------------------------------
/ino/internal/input/touch_mobile.go:
--------------------------------------------------------------------------------
1 | //go:build android || ios
2 |
3 | package input
4 |
5 | func isTouchPrimaryInput() bool {
6 | return true
7 | }
8 |
--------------------------------------------------------------------------------
/ino/internal/input/touch_notmobile.go:
--------------------------------------------------------------------------------
1 | //go:build !android && !ios
2 |
3 | package input
4 |
5 | func isTouchPrimaryInput() bool {
6 | return false
7 | }
8 |
--------------------------------------------------------------------------------
/ino/internal/lang/lang_default.go:
--------------------------------------------------------------------------------
1 | //go:build !js && !steam
2 |
3 | package lang
4 |
5 | import (
6 | "golang.org/x/text/language"
7 | )
8 |
9 | func SystemLang() language.Tag {
10 | // TODO: Implement this correctly
11 | return language.English
12 | }
13 |
--------------------------------------------------------------------------------
/ino/internal/lang/lang_js.go:
--------------------------------------------------------------------------------
1 | package lang
2 |
3 | import (
4 | "syscall/js"
5 |
6 | "golang.org/x/text/language"
7 |
8 | "github.com/hajimehoshi/go-inovation/ino/internal/text"
9 | )
10 |
11 | func SystemLang() language.Tag {
12 | nav := js.Global().Get("navigator")
13 | if !nav.Truthy() {
14 | return language.Japanese
15 | }
16 | str := nav.Get("language").String()
17 | newLang, _ := language.Parse(str)
18 | base, _ := newLang.Base()
19 | newLang, _ = language.Compose(base)
20 | for _, l := range text.Languages() {
21 | if newLang == l {
22 | return newLang
23 | }
24 | }
25 | return language.English
26 | }
27 |
--------------------------------------------------------------------------------
/ino/internal/lang/lang_steam.go:
--------------------------------------------------------------------------------
1 | //go:build !js && steam
2 |
3 | package lang
4 |
5 | import (
6 | "os"
7 |
8 | "github.com/hajimehoshi/go-steamworks"
9 | "golang.org/x/text/language"
10 | )
11 |
12 | const appID = 1710390
13 |
14 | func init() {
15 | if steamworks.RestartAppIfNecessary(appID) {
16 | os.Exit(1)
17 | }
18 | if !steamworks.Init() {
19 | panic("steamworks.Init failed")
20 | }
21 | }
22 |
23 | func SystemLang() language.Tag {
24 | switch steamworks.SteamApps().GetCurrentGameLanguage() {
25 | case "english":
26 | return language.English
27 | case "japanese":
28 | return language.Japanese
29 | }
30 | return language.English
31 | }
32 |
--------------------------------------------------------------------------------
/ino/internal/text/text.go:
--------------------------------------------------------------------------------
1 | package text
2 |
3 | import (
4 | "golang.org/x/text/language"
5 | )
6 |
7 | type TextID int
8 |
9 | const (
10 | TextIDStart TextID = iota
11 | TextIDStartLunker
12 | TextIDStartTouch
13 | TextIDOpening
14 | TextIDEnding
15 | TextIDEndingScore1
16 | TextIDEndingScore2
17 | TextIDEndingScore3
18 | TextIDSecretCommand
19 | TextIDSecretClear
20 | TextIDItemPowerUp
21 | TextIDItemFuji
22 | TextIDItemBushi
23 | TextIDItemApple
24 | TextIDItemV
25 | TextIDItemTaka
26 | TextIDItemShoulder
27 | TextIDItemDagger
28 | TextIDItemKatakata
29 | TextIDItemNasu
30 | TextIDItemBonus
31 | TextIDItemNurse
32 | TextIDItemNazuna
33 | TextIDItemGameHell
34 | TextIDItemGundam
35 | TextIDItemPoed
36 | TextIDItemMilestone
37 | TextIDItem1Yen
38 | TextIDItemTriangle
39 | TextIDItemOmega
40 | TextIDItemLife
41 | )
42 |
43 | var texts = map[language.Tag]map[TextID]string{
44 | language.Japanese: {
45 | TextIDStart: "すぺーす たたく はじまる!",
46 | TextIDStartLunker: "らんかー もーど はじまる!",
47 | TextIDStartTouch: "がめん たっち はじまる!",
48 | TextIDOpening: `めが さめたら
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 | TextIDEnding: `あつめた、じんぎたちが かがやきだす!
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 | 2007 しんねん はじまる!
105 | あけましておめでとう!
106 |
107 |
108 |
109 |
110 |
111 | ―― ここから くれじっと ――
112 |
113 |
114 | いのべーじょん2007
115 | ** くれじっとの なかに いる **
116 |
117 |
118 |
119 | すーぱー ざつよう にんげん
120 | おめが / ( ゜ワ゜)ノ
121 |
122 | おんがく にんげん
123 | どん
124 |
125 | ふいーるど まっぷ にんげん
126 | おめが / ( ゜ワ゜)ノ
127 | げっく
128 | ずい
129 | 351
130 |
131 | たいとる めいめい にんげん
132 | わんきち
133 |
134 | てすとぷれい にんげん
135 | げーむへる2000
136 | げっく
137 | 351
138 | ずぃ
139 | あかじゃ
140 |
141 | すべさる さんくす にんげん
142 | げーむ せいさく ぎじゅつ いた
143 | どにちまでに げーむを つくる すれ
144 |
145 | HTML5 いしょく
146 | はねだ
147 |
148 | ごー げんご いしょく
149 | ほしはじめ
150 |
151 |
152 | ぷろどぅーすど ばい
153 | おめが
154 |
155 |
156 |
157 | ―― くれじっと ここまで ――
158 |
159 | えんどう おふろに はいる`,
160 | TextIDEndingScore1: "せいせき はぴょう",
161 | TextIDEndingScore2: "かくとく あいてむ",
162 | TextIDEndingScore3: "くりあ たいむ",
163 | TextIDSecretCommand: `たいとるで
164 |
165 | ひだり ひだり ひだり
166 | みぎ みぎ みぎ
167 | ひだり みぎ`,
168 | TextIDSecretClear: `おめでとう。
169 |
170 | あなたは
171 | ぎじゅつ さる
172 | です。`,
173 | TextIDItemPowerUp: `「みずぐすり」を てに いれた。
174 | 「てーれってれー」
175 | 「じゃんぷりょくが あっぷ。
176 | くうちゅう じゃんぷが 1かい
177 | くわわる くわわる!`,
178 | TextIDItemFuji: `「ふじ」を てに いれた。
179 | じんぎの ひとつ。
180 | ふんかしない かざん。
181 | きゅうかざん って
182 | いうんだって。`,
183 | TextIDItemBushi: `「ぶし」を てに いれた。
184 | じゃぱにーず ないと。
185 | あめりか だいとうりょうも ぶしどー。
186 | さむらーい さむらーい ぶしどー。`,
187 | TextIDItemApple: `「ふじりんご」を てに いれた。
188 | あかい かじつ。
189 | あーかーい りんごーにー
190 | くちびーる よーせーてー。`,
191 | TextIDItemV: `「ぶい」を てに いれた。
192 | たたかいの さけび!
193 | 「しんかとは ひとと げーむの
194 | がったいだ!」`,
195 | TextIDItemTaka: `「たか」を てに いれた。
196 | じんぎの ひとつ。
197 | そらの はんたー。
198 | こだいあすてかでは
199 | かみの つかい なんだ。`,
200 | TextIDItemShoulder: `「かた」を てに いれた。
201 | どうたいの うえ、
202 | うでの つけね。
203 | かたが あかいと
204 | じかんに おくれる。`,
205 | TextIDItemDagger: `「だがー」を てに いれた。
206 | みじかい けん
207 | ひだりてたての かわりに。
208 | こがたなの かわりに。
209 | ぼうけんの おともに どうぞ。`,
210 | TextIDItemKatakata: `「かたかた」を てに いれた。
211 | かたかた…
212 | 「これは まるたーがいすと…」
213 | 「ちがう!ぷらずま だ!!」`,
214 | TextIDItemNasu: `「なす」を てに いれた。
215 | じんぎの ひとつ。
216 | むらさきに かがやく
217 | やさいの おうさま
218 | でも あまり たべたきが しない。`,
219 | TextIDItemBonus: `「ぼうなす」を てに いれた。
220 | あ ぼうなす!
221 | ふぇいたりてぃ ぼうなす!
222 | ぱしふぃすと ぼうなす!
223 | でぃす いず ざ ぼうなす!`,
224 | TextIDItemNurse: `「なーす」を てに いれた。
225 | 「かんごふでは ない!
226 | 『かんごし』と よべ!
227 | この ペいしえんと どもめ!」`,
228 | TextIDItemNazuna: `「なずな」を てに いれた。
229 | べつめい、ぺんぺんぐさ。
230 | なずなが とおったあとには
231 | ぺんぺんぐさすら のこらないという`,
232 | TextIDItemGameHell: `「げーむへる」を てに いれた。
233 | ようこそ。
234 | げーむ せいさくしゃと
235 | その しゅうへんの ための
236 | こみゅにていへ。`,
237 | TextIDItemGundam: `「じっしゃがんだむ」を てに いれた。
238 | 「そうさは かんたんだ。
239 | せんとう こんぴゅーたの
240 | すいっちを いれるだけで いい。」`,
241 | TextIDItemPoed: `「ほえど」を てに いれた。
242 | 「ふん。
243 | おもしろくなって
244 | きやがったぜ!」`,
245 | TextIDItemMilestone: `「まいるまーく」を てに いれた。
246 | さいしんさく「からす」
247 | ぜっさん かどうちゅう でしゅー`,
248 | TextIDItem1Yen: `「いちえんさつ」を てに いれた。
249 | 「くらくて よくみえないわ」
250 | 「ほうら あかるいだろう」
251 | 「『くらくて よくみえないわ』と
252 | かいてある」`,
253 | TextIDItemTriangle: `「とらいあんぐる」を てに いれた。
254 | すべって ころんで おおいたけん。
255 | しゃちょうは いま
256 | どうしているのか…`,
257 | TextIDItemOmega: `「おめがの くんしょう」を てに いれた。
258 | こんな げーむに
259 | まじに なって
260 | どうも ありがとう`,
261 | TextIDItemLife: `「はーとの うつわ」を てに いれた。
262 | でれででーん!
263 | らいふの じょうげんを
264 | 1ふやしてあげる
265 | ああ、なんて たくましいの…`,
266 | },
267 | language.English: {
268 | TextIDStart: "PRESS SPACE BEGIN!",
269 | TextIDStartLunker: "LUNKER MODE BEGIN!",
270 | TextIDStartTouch: "TOUCH SCREEN BEGIN!",
271 | TextIDOpening: `when I wake up
272 | I become Wild bore
273 | calm down me
274 | ** stay in dream **
275 |
276 |
277 |
278 |
279 |
280 | in a dream
281 | a Prophet Druid man
282 | He telling me
283 | can finding THE Three "GOT ICONs"
284 | this dream's HERO
285 | you. just only YOU!
286 |
287 |
288 |
289 |
290 |
291 | beat any traps
292 | Telling of
293 | "The first dream of the year of Japan"
294 | explor "Imperial Regalia of Japan"
295 | This is the FATE of me
296 |
297 |
298 |
299 |
300 |
301 | My WILD BORE's Heart get excited.`,
302 | TextIDEnding: `shining "Imperial Regalia of Japan"
303 | OOOMPF!
304 |
305 |
306 |
307 | Hop Step Jump
308 | carllouis!
309 |
310 |
311 |
312 | Before long A factor was
313 | her Intention had calling to original place
314 | Recurrence...
315 | Memoried to His Heart
316 | Recall it makes Mind of The Creation
317 |
318 |
319 | 2007 spring has come!
320 |
321 |
322 | a Happy New Year!
323 |
324 |
325 |
326 |
327 |
328 | INNOVATION 2007
329 |
330 |
331 |
332 | Super Trivial Works
333 | O-MEGA
334 |
335 |
336 |
337 | composer man
338 | dong
339 |
340 |
341 |
342 | Field Maps Design
343 | O-MEGA
344 | Gekku
345 | Zy
346 | 351
347 |
348 |
349 |
350 | Title naming
351 | wang-zhi
352 |
353 |
354 |
355 | Test Playing man
356 | Game-Hell 2000
357 | Gek
358 | 351
359 | Zi
360 | Akaja
361 |
362 |
363 |
364 | EngRish translation
365 | Eki
366 | Dong
367 | O-MEGA
368 |
369 |
370 |
371 | Special Thanks man
372 | Game Dev. BBS users
373 | www.2ch.net Thread "Game Deveropment"
374 |
375 |
376 |
377 | Porting to HTML5
378 | Haneda
379 |
380 |
381 |
382 | Porting to Go
383 | Hajime Hoshi
384 |
385 |
386 |
387 | Produced by
388 | O-MEGA
389 |
390 |
391 |
392 | EVZO-END get bath`,
393 | TextIDEndingScore1: "Results",
394 | TextIDEndingScore2: "You Got ICONS",
395 | TextIDEndingScore3: "Clear Time",
396 | TextIDSecretCommand: `at Title Screen
397 |
398 | L L L
399 | R R R
400 | L R`,
401 | TextIDSecretClear: `Congratulations!
402 |
403 | You are
404 | the
405 | technical monkey.`,
406 | TextIDItemPowerUp: `You Grab "Water Medicine"
407 | TA-RA-TERAH!!
408 | JUMP UP
409 | you got "M. Jordan's AIR NIKE"
410 | increase INCREASES!`,
411 | TextIDItemFuji: `You Grab a "FUJIYAMA"
412 | *An Imperial Regalia*
413 | Throw the One Ring Frodo!`,
414 | TextIDItemBushi: `You Feel "BUSHI-DO"
415 | Japanese SAMURAI Spilit
416 | USMC, Marines have BUSHI-DO
417 | SAMURAI SAMURAI BUSHI-DO`,
418 | TextIDItemApple: `You Grab Big Apple(fuji-ringo)
419 | Red Sweety
420 | Let it be lalala`,
421 | TextIDItemV: `You Grab "V of Victory"
422 | war cry!
423 | Me Humanbeing with a VIDEO GAME
424 | PILDER ON!`,
425 | TextIDItemTaka: `You catch a Hawk(Taka).
426 | *an Imperial Regalia*
427 | The President of Sky.
428 | In ancient Aztec
429 | A messenger of God`,
430 | TextIDItemShoulder: `You got a RED-SHOULDER(Kata)
431 | upper bodie The root of Arms
432 | Red-Shoulder`,
433 | TextIDItemDagger: `You Got a Dagger
434 | Short sword
435 | the only friend
436 | on your quest`,
437 | TextIDItemKatakata: `You Grab "Katakata"
438 | strange sound
439 | RATTLE-RATTLE...
440 | Poltergeist!?
441 | NO! ask to Mulder!`,
442 | TextIDItemNasu: `You Got Eggplant (Nasu)
443 | *An Imperial Regalia*
444 | Purple Shining
445 | King of Vegetable
446 | But I've never satisfied with this`,
447 | TextIDItemBonus: `You Got "Bonus"
448 | A Bonus!
449 | Fatality Bonus!
450 | Pacifist Bonus!
451 | This is the Bonus!`,
452 | TextIDItemNurse: `You Grab "Nurse"
453 | I'm not an angel in white
454 | I'm a goddess of hell
455 | You Patients!`,
456 | TextIDItemNazuna: `You got "Nazuna"
457 | It is called
458 | "Shepherd's-purse"
459 | in English
460 | Symbol of doom`,
461 | TextIDItemGameHell: `You Grab “GameHel12000"
462 | Helcome.
463 | We are an community of
464 | Japanese indie game developers.`,
465 | TextIDItemGundam: `You Grab "GUNDAM 0079"
466 | Control is easy
467 | All you have to do is
468 | switching on a battle computer`,
469 | TextIDItemPoed: `You Grab "Po'ed"
470 | Ha!
471 | It's getting more interesting!`,
472 | TextIDItemMilestone: `You got "Milestone Mark"
473 | All your wii are belong to
474 | our doomsday device KAROUS.`,
475 | TextIDItem1Yen: `You Got 1 Yen.
476 | In ancient Japan
477 | It was used as a
478 | substitute for light`,
479 | TextIDItemTriangle: `You Got "Triangle Service"
480 | Slip Trip Oita-Pref.
481 | Where is the Boss?`,
482 | TextIDItemOmega: `You Got "O-mega Medal"
483 | Thank you for playing
484 | such a masochistic game.`,
485 | TextIDItemLife: `You Got a Heart Container
486 | DeDeDe-Deng!!
487 | Increase your MAX LIFE.
488 | REAL MEN!!`,
489 | },
490 | }
491 |
492 | func Get(lang language.Tag, id TextID) string {
493 | return texts[lang][id]
494 | }
495 |
496 | func Languages() []language.Tag {
497 | // TODO: Sort
498 | langs := []language.Tag{}
499 | for lang := range texts {
500 | langs = append(langs, lang)
501 | }
502 | return langs
503 | }
504 |
--------------------------------------------------------------------------------
/ino/main.go:
--------------------------------------------------------------------------------
1 | package ino
2 |
3 | import (
4 | "fmt"
5 | "image/color"
6 | "math/rand"
7 | "strconv"
8 | "strings"
9 | "time"
10 |
11 | "github.com/hajimehoshi/ebiten/v2"
12 | "golang.org/x/text/language"
13 |
14 | "github.com/hajimehoshi/go-inovation/ino/internal/audio"
15 | "github.com/hajimehoshi/go-inovation/ino/internal/draw"
16 | "github.com/hajimehoshi/go-inovation/ino/internal/font"
17 | "github.com/hajimehoshi/go-inovation/ino/internal/input"
18 | "github.com/hajimehoshi/go-inovation/ino/internal/text"
19 | )
20 |
21 | const (
22 | ScreenWidth = draw.ScreenWidth
23 | ScreenHeight = draw.ScreenHeight
24 | )
25 |
26 | const (
27 | ENDINGMAIN_STATE_STAFFROLL = iota
28 | ENDINGMAIN_STATE_RESULT
29 | )
30 |
31 | type GameStateMsg int
32 |
33 | const (
34 | GAMESTATE_MSG_NONE GameStateMsg = iota
35 | GAMESTATE_MSG_REQ_TITLE
36 | GAMESTATE_MSG_REQ_GAME
37 | GAMESTATE_MSG_REQ_OPENING
38 | GAMESTATE_MSG_REQ_ENDING
39 | GAMESTATE_MSG_REQ_SECRET_COMMAND
40 | GAMESTATE_MSG_REQ_SECRET_CLEAR
41 | )
42 |
43 | type TitleScene struct {
44 | gameStateMsg GameStateMsg
45 | timer int
46 | offsetX int
47 | offsetY int
48 | lunkerMode bool
49 | lunkerCommand int
50 | }
51 |
52 | func init() {
53 | rand.Seed(time.Now().UnixNano())
54 | }
55 |
56 | func (t *TitleScene) Update(game *Game) {
57 | t.timer++
58 | if t.timer%5 == 0 {
59 | t.offsetX = rand.Intn(5) - 3
60 | t.offsetY = rand.Intn(5) - 3
61 | }
62 |
63 | if (input.Current().IsActionKeyJustPressed() || input.Current().IsSpaceJustTouched()) && t.timer > 5 {
64 | t.gameStateMsg = GAMESTATE_MSG_REQ_OPENING
65 |
66 | if t.lunkerMode {
67 | game.gameData = NewGameData(GAMEMODE_LUNKER)
68 | } else {
69 | game.gameData = NewGameData(GAMEMODE_NORMAL)
70 | }
71 | }
72 |
73 | // ランカー・モード・コマンド
74 | switch t.lunkerCommand {
75 | case 0, 1, 2, 6:
76 | if input.Current().IsKeyJustPressed(ebiten.KeyLeft) {
77 | t.lunkerCommand++
78 | } else if input.Current().IsKeyJustPressed(ebiten.KeyRight) || input.Current().IsKeyJustPressed(ebiten.KeyUp) || input.Current().IsKeyJustPressed(ebiten.KeyDown) {
79 | t.lunkerCommand = 0
80 | }
81 | case 3, 4, 5, 7:
82 | if input.Current().IsKeyJustPressed(ebiten.KeyRight) {
83 | t.lunkerCommand++
84 | } else if input.Current().IsKeyJustPressed(ebiten.KeyLeft) || input.Current().IsKeyJustPressed(ebiten.KeyUp) || input.Current().IsKeyJustPressed(ebiten.KeyDown) {
85 | t.lunkerCommand = 0
86 | }
87 | default:
88 | break
89 | }
90 | if t.lunkerCommand > 7 {
91 | t.lunkerCommand = 0
92 | t.lunkerMode = !t.lunkerMode
93 | }
94 |
95 | if input.Current().IsLanguageSwitcherPressed() {
96 | switch game.lang {
97 | case language.Japanese:
98 | game.lang = language.English
99 | case language.English:
100 | game.lang = language.Japanese
101 | }
102 | }
103 |
104 | switch game.lang {
105 | case language.English:
106 | ebiten.SetWindowTitle("INNO VATION! 2007")
107 | case language.Japanese:
108 | ebiten.SetWindowTitle("いの べーしょん! 2007")
109 | }
110 | }
111 |
112 | func (t *TitleScene) Draw(screen *ebiten.Image, game *Game) {
113 | textID := text.TextIDStart
114 | clr := color.Black
115 | if !game.transparent {
116 | if t.lunkerMode {
117 | draw.Draw(screen, "bg", 0, 0, 0, 240, draw.ScreenWidth, draw.ScreenHeight)
118 | textID = text.TextIDStartLunker
119 | clr = color.White
120 | } else {
121 | draw.Draw(screen, "bg", 0, 0, 0, 0, draw.ScreenWidth, draw.ScreenHeight)
122 | if input.Current().IsTouchEnabled() {
123 | textID = text.TextIDStartTouch
124 | }
125 | }
126 | }
127 |
128 | str := text.Get(game.lang, textID)
129 | x := (draw.ScreenWidth-font.Width(str))/2 + t.offsetX
130 | y := (draw.ScreenHeight-240)/2 + 160 + t.offsetY
131 | font.DrawText(screen, str, x, y, clr)
132 |
133 | // Draw the title.
134 | key := "msg_" + game.lang.String()
135 | draw.Draw(screen, key, (draw.ScreenWidth-256)/2, 32+(draw.ScreenHeight-240)/2, 0, 0, 256, 48)
136 |
137 | // Draw the language switcher.
138 | font.DrawText(screen, "Language", 320-48, 0, color.RGBA{0x80, 0x80, 0x80, 0xff})
139 | }
140 |
141 | func (t *TitleScene) Msg() GameStateMsg {
142 | return t.gameStateMsg
143 | }
144 |
145 | type OpeningScene struct {
146 | gameStateMsg GameStateMsg
147 | timer int
148 | texts map[language.Tag][]string
149 | }
150 |
151 | const (
152 | OPENING_SCROLL_SPEED = 3
153 | )
154 |
155 | func (o *OpeningScene) Update(game *Game) {
156 | o.timer++
157 |
158 | if input.Current().IsActionKeyPressed() || input.Current().IsSpaceTouched() {
159 | o.timer += 20
160 | }
161 | scrollLen := font.Height(text.Get(game.lang, text.TextIDOpening)) + draw.ScreenHeight
162 | if o.timer/OPENING_SCROLL_SPEED > scrollLen {
163 | o.gameStateMsg = GAMESTATE_MSG_REQ_GAME
164 | audio.PauseBGM()
165 | }
166 | }
167 |
168 | func (o *OpeningScene) Draw(screen *ebiten.Image, game *Game) {
169 | if !game.transparent {
170 | draw.Draw(screen, "bg", 0, 0, 0, 480, 320, 240)
171 | }
172 |
173 | if _, ok := o.texts[game.lang]; !ok {
174 | if o.texts == nil {
175 | o.texts = map[language.Tag][]string{}
176 | }
177 | o.texts[game.lang] = strings.Split(text.Get(game.lang, text.TextIDOpening), "\n")
178 | }
179 | for i, line := range o.texts[game.lang] {
180 | x := (draw.ScreenWidth - font.Width(line)) / 2
181 | y := draw.ScreenHeight - (o.timer / OPENING_SCROLL_SPEED) + i*font.LineHeight
182 | font.DrawText(screen, line, x, y, color.Black)
183 | }
184 | }
185 |
186 | func (o *OpeningScene) Msg() GameStateMsg {
187 | return o.gameStateMsg
188 | }
189 |
190 | type EndingScene struct {
191 | gameStateMsg GameStateMsg
192 | timer int
193 | bgmFadingTimer int
194 | state int
195 | texts map[language.Tag][]string
196 | }
197 |
198 | const (
199 | ENDING_SCROLL_SPEED = 3
200 | )
201 |
202 | func (e *EndingScene) Update(game *Game) {
203 | e.timer++
204 | switch e.state {
205 | case ENDINGMAIN_STATE_STAFFROLL:
206 | if input.Current().IsActionKeyPressed() || input.Current().IsSpaceTouched() {
207 | e.timer += 20
208 | }
209 | scrollLen := font.Height(text.Get(game.lang, text.TextIDEnding)) + draw.ScreenHeight
210 | if e.timer/ENDING_SCROLL_SPEED > scrollLen {
211 | e.timer = 0
212 | e.state = ENDINGMAIN_STATE_RESULT
213 | }
214 | case ENDINGMAIN_STATE_RESULT:
215 | const max = 5 * 60
216 | e.bgmFadingTimer++
217 | switch {
218 | case e.bgmFadingTimer == max:
219 | audio.PauseBGM()
220 | case e.bgmFadingTimer < max:
221 | vol := 1 - (float64(e.bgmFadingTimer) / max)
222 | audio.SetBGMVolume(vol)
223 | }
224 | if (input.Current().IsActionKeyJustPressed() || input.Current().IsSpaceJustTouched()) && e.timer > 5 {
225 | // 条件を満たしていると隠し画面へ
226 | if game.gameData.IsGetOmega() {
227 | if game.gameData.lunkerMode {
228 | e.gameStateMsg = GAMESTATE_MSG_REQ_SECRET_CLEAR
229 | } else {
230 | e.gameStateMsg = GAMESTATE_MSG_REQ_SECRET_COMMAND
231 | }
232 | return
233 | }
234 | e.gameStateMsg = GAMESTATE_MSG_REQ_TITLE
235 | audio.PauseBGM()
236 | }
237 | }
238 | }
239 |
240 | func (e *EndingScene) Draw(screen *ebiten.Image, game *Game) {
241 | if !game.transparent {
242 | draw.Draw(screen, "bg", 0, 0, 0, 480, 320, 240)
243 | }
244 |
245 | switch e.state {
246 | case ENDINGMAIN_STATE_STAFFROLL:
247 | if _, ok := e.texts[game.lang]; !ok {
248 | if e.texts == nil {
249 | e.texts = map[language.Tag][]string{}
250 | }
251 | e.texts[game.lang] = strings.Split(text.Get(game.lang, text.TextIDEnding), "\n")
252 | }
253 | for i, line := range e.texts[game.lang] {
254 | x := (draw.ScreenWidth - font.Width(line)) / 2
255 | y := draw.ScreenHeight - (e.timer / ENDING_SCROLL_SPEED) + i*font.LineHeight
256 | font.DrawText(screen, line, x, y, color.Black)
257 | }
258 | case ENDINGMAIN_STATE_RESULT:
259 | lines := []string{
260 | text.Get(game.lang, text.TextIDEndingScore1),
261 | "",
262 | text.Get(game.lang, text.TextIDEndingScore2),
263 | strconv.Itoa(game.gameData.GetItemCount()),
264 | "",
265 | text.Get(game.lang, text.TextIDEndingScore3),
266 | fmt.Sprintf("%.2f", float64(game.gameData.TimeInFrame())/60),
267 | }
268 | for i, line := range lines {
269 | x := (draw.ScreenWidth - font.Width(line)) / 2
270 | font.DrawText(screen, line, x, (draw.ScreenHeight-160)/2+16*i, color.Black)
271 | }
272 | }
273 | }
274 |
275 | func (e *EndingScene) Msg() GameStateMsg {
276 | return e.gameStateMsg
277 | }
278 |
279 | type SecretType int
280 |
281 | const (
282 | SecretTypeCommand SecretType = iota
283 | SecretTypeClear
284 | )
285 |
286 | type SecretScene struct {
287 | gameStateMsg GameStateMsg
288 | timer int
289 | secretType SecretType
290 | }
291 |
292 | func NewSecretScene(secretType SecretType) *SecretScene {
293 | return &SecretScene{
294 | secretType: secretType,
295 | }
296 | }
297 |
298 | func (s *SecretScene) Update(game *Game) {
299 | s.timer++
300 | if (input.Current().IsActionKeyJustPressed() || input.Current().IsSpaceJustTouched()) && s.timer > 5 {
301 | s.gameStateMsg = GAMESTATE_MSG_REQ_TITLE
302 | }
303 | }
304 |
305 | func (s *SecretScene) Draw(screen *ebiten.Image, game *Game) {
306 | if !game.transparent {
307 | draw.Draw(screen, "bg", 0, 0, 0, 240, 320, 240)
308 | }
309 | var textID text.TextID
310 | switch s.secretType {
311 | case SecretTypeCommand:
312 | textID = text.TextIDSecretCommand
313 | case SecretTypeClear:
314 | textID = text.TextIDSecretClear
315 | default:
316 | panic("not reached")
317 | }
318 | str := text.Get(game.lang, textID)
319 | y := (draw.ScreenHeight - font.Height(str)) / 2
320 | for i, line := range strings.Split(str, "\n") {
321 | x := (draw.ScreenWidth - font.Width(line)) / 2
322 | font.DrawText(screen, line, x, y+i*font.LineHeight, color.White)
323 | }
324 | }
325 |
326 | func (s *SecretScene) Msg() GameStateMsg {
327 | return s.gameStateMsg
328 | }
329 |
330 | type GameScene struct {
331 | gameStateMsg GameStateMsg
332 | player *Player
333 | }
334 |
335 | func NewGameScene(game *Game) *GameScene {
336 | g := &GameScene{
337 | player: NewPlayer(game.gameData),
338 | }
339 | return g
340 | }
341 |
342 | func (g *GameScene) Update(game *Game) {
343 | g.gameStateMsg = g.player.Update()
344 | }
345 |
346 | func (g *GameScene) Draw(screen *ebiten.Image, game *Game) {
347 | if !game.transparent {
348 | if game.gameData.lunkerMode {
349 | draw.Draw(screen, "bg", 0, 0, 0, 240, draw.ScreenWidth, draw.ScreenHeight)
350 | } else {
351 | draw.Draw(screen, "bg", 0, 0, 0, 0, draw.ScreenWidth, draw.ScreenHeight)
352 | }
353 | }
354 | g.player.Draw(screen, game)
355 | if input.Current().IsTouchEnabled() {
356 | draw.DrawTouchButtons(screen)
357 | }
358 | }
359 |
360 | func (g *GameScene) Msg() GameStateMsg {
361 | return g.gameStateMsg
362 | }
363 |
364 | type Scene interface {
365 | Update(g *Game) // TODO: Should return errors
366 | Draw(screen *ebiten.Image, g *Game)
367 | Msg() GameStateMsg
368 | }
369 |
--------------------------------------------------------------------------------
/ino/player.go:
--------------------------------------------------------------------------------
1 | package ino
2 |
3 | import (
4 | "math"
5 |
6 | "github.com/hajimehoshi/ebiten/v2"
7 |
8 | "github.com/hajimehoshi/go-inovation/ino/internal/audio"
9 | "github.com/hajimehoshi/go-inovation/ino/internal/draw"
10 | "github.com/hajimehoshi/go-inovation/ino/internal/field"
11 | "github.com/hajimehoshi/go-inovation/ino/internal/fieldtype"
12 | "github.com/hajimehoshi/go-inovation/ino/internal/input"
13 | )
14 |
15 | type PlayerState int
16 |
17 | const (
18 | PLAYERSTATE_START PlayerState = iota
19 | PLAYERSTATE_NORMAL
20 | PLAYERSTATE_ITEMGET
21 | PLAYERSTATE_MUTEKI
22 | PLAYERSTATE_DEAD
23 | )
24 |
25 | const (
26 | PLAYER_SPEED = 2.0
27 | PLAYER_GRD_ACCRATIO = 0.04
28 | PLAYER_AIR_ACCRATIO = 0.01
29 | PLAYER_JUMP = -4.0
30 | PLAYER_GRAVITY = 0.2
31 | PLAYER_FALL_SPEEDMAX = 4.0
32 | WAIT_TIMER_INTERVAL = 10
33 | LIFE_RATIO = 400
34 | MUTEKI_INTERVAL = 50
35 | START_WAIT_INTERVAL = 50
36 | SCROLLPANEL_SPEED = 2.0
37 |
38 | LUNKER_JUMP_DAMAGE1 = 40.0
39 | LUNKER_JUMP_DAMAGE2 = 96.0
40 | )
41 |
42 | type Player struct {
43 | life int
44 | jumpCnt int
45 | timer int
46 | position PositionF
47 | speed PositionF
48 | direction int
49 | jumpedPoint PositionF
50 | state PlayerState
51 | itemGet fieldtype.FieldType
52 | waitTimer int
53 | gameData *GameData // TODO(hajimehoshi): Remove this?
54 | view *View
55 | field *field.Field
56 | }
57 |
58 | func NewPlayer(gameData *GameData) *Player {
59 | f := field.New(field_data)
60 | x, y := f.GetStartPoint()
61 | startPointF := PositionF{float64(x), float64(y)}
62 | audio.PlayBGM(audio.BGM0)
63 | return &Player{
64 | gameData: gameData,
65 | field: f,
66 | life: gameData.lifeMax * LIFE_RATIO,
67 | position: startPointF,
68 | jumpedPoint: startPointF,
69 | view: NewView(startPointF),
70 | }
71 | }
72 |
73 | func (p *Player) onWall() bool {
74 | if p.toFieldOfsY() > field.CHAR_SIZE/4 {
75 | return false
76 | }
77 | if p.field.IsRidable(p.toFieldX(), p.toFieldY()+1) && p.toFieldOfsX() < field.CHAR_SIZE*7/8 {
78 | return true
79 | }
80 | if p.field.IsRidable(p.toFieldX()+1, p.toFieldY()+1) && p.toFieldOfsX() > field.CHAR_SIZE/8 {
81 | return true
82 | }
83 | return false
84 | }
85 |
86 | func (p *Player) isFallable() bool {
87 | if !p.onWall() {
88 | return false
89 | }
90 | if p.field.IsWall(p.toFieldX(), p.toFieldY()+1) && p.toFieldOfsX() < field.CHAR_SIZE*7/8 {
91 | return false
92 | }
93 | if p.field.IsWall(p.toFieldX()+1, p.toFieldY()+1) && p.toFieldOfsX() > field.CHAR_SIZE/8 {
94 | return false
95 | }
96 | return true
97 | }
98 |
99 | func (p *Player) isUpperWallBoth() bool {
100 | if p.toFieldOfsY() < field.CHAR_SIZE/2 {
101 | return false
102 | }
103 | if p.field.IsWall(p.toFieldX(), p.toFieldY()) && p.field.IsWall(p.toFieldX()+1, p.toFieldY()) {
104 | return true
105 | }
106 | return false
107 | }
108 |
109 | func (p *Player) isUpperWall() bool {
110 | if p.toFieldOfsY() < field.CHAR_SIZE/2 {
111 | return false
112 | }
113 | if p.field.IsWall(p.toFieldX(), p.toFieldY()) && p.toFieldOfsX() < field.CHAR_SIZE*7/8 {
114 | return true
115 | }
116 | if p.field.IsWall(p.toFieldX()+1, p.toFieldY()) && p.toFieldOfsX() > field.CHAR_SIZE/8 {
117 | return true
118 | }
119 | return false
120 | }
121 |
122 | func (p *Player) isLeftWall() bool {
123 | if p.field.IsWall(p.toFieldX(), p.toFieldY()) {
124 | return true
125 | }
126 | if p.field.IsWall(p.toFieldX(), p.toFieldY()+1) && p.toFieldOfsY() > field.CHAR_SIZE/8 {
127 | return true
128 | }
129 | return false
130 | }
131 |
132 | func (p *Player) isRightWall() bool {
133 | if p.field.IsWall(p.toFieldX()+1, p.toFieldY()) {
134 | return true
135 | }
136 | if p.field.IsWall(p.toFieldX()+1, p.toFieldY()+1) && p.toFieldOfsY() > field.CHAR_SIZE/8 {
137 | return true
138 | }
139 | return false
140 | }
141 |
142 | func (p *Player) normalizeToRight() {
143 | p.position.X = float64(p.toFieldX() * field.CHAR_SIZE)
144 | p.speed.X = 0
145 | }
146 |
147 | func (p *Player) normalizeToLeft() {
148 | p.position.X = float64((p.toFieldX() + 1) * field.CHAR_SIZE)
149 | p.speed.X = 0
150 | }
151 |
152 | func (p *Player) normalizeToUpper() {
153 | if p.speed.Y < 0 {
154 | p.speed.Y = 0
155 | }
156 | p.position.Y = float64(field.CHAR_SIZE * (p.toFieldY() + 1))
157 | }
158 |
159 | func (p *Player) toFieldX() int {
160 | return int(p.position.X) / field.CHAR_SIZE
161 | }
162 |
163 | func (p *Player) toFieldY() int {
164 | return int(p.position.Y) / field.CHAR_SIZE
165 | }
166 |
167 | func (p *Player) toFieldOfsX() int {
168 | return int(p.position.X) % field.CHAR_SIZE
169 | }
170 |
171 | func (p *Player) toFieldOfsY() int {
172 | return int(p.position.Y) % field.CHAR_SIZE
173 | }
174 |
175 | func (p *Player) Update() GameStateMsg {
176 | msg := GAMESTATE_MSG_NONE
177 | p.field.Update()
178 | switch p.state {
179 | case PLAYERSTATE_START:
180 | p.waitTimer++
181 | if p.waitTimer > START_WAIT_INTERVAL {
182 | p.state = PLAYERSTATE_NORMAL
183 | }
184 |
185 | case PLAYERSTATE_NORMAL:
186 | p.moveByInput()
187 | p.moveNormal()
188 | if p.life < p.gameData.lifeMax*LIFE_RATIO {
189 | o_life := p.life
190 | p.life++
191 | if (p.life / LIFE_RATIO) != (o_life / LIFE_RATIO) {
192 | audio.PlaySE(audio.SE_HEAL)
193 | }
194 | }
195 |
196 | case PLAYERSTATE_ITEMGET:
197 | p.moveItemGet()
198 | if p.state != PLAYERSTATE_ITEMGET {
199 | if p.gameData.IsGameClear() {
200 | msg = GAMESTATE_MSG_REQ_ENDING
201 | }
202 | }
203 |
204 | case PLAYERSTATE_MUTEKI:
205 | p.moveByInput()
206 | p.moveNormal()
207 | p.waitTimer++
208 | if p.waitTimer > MUTEKI_INTERVAL {
209 | p.state = PLAYERSTATE_NORMAL
210 | }
211 |
212 | case PLAYERSTATE_DEAD:
213 | p.moveNormal()
214 | audio.PauseBGM()
215 | if input.Current().IsActionKeyPressed() && p.waitTimer > 15 {
216 | msg = GAMESTATE_MSG_REQ_TITLE
217 | }
218 | }
219 | if p.life < LIFE_RATIO {
220 | if p.state != PLAYERSTATE_DEAD {
221 | p.waitTimer = 0
222 | }
223 | p.state = PLAYERSTATE_DEAD
224 | p.direction = 0
225 | p.waitTimer++
226 | }
227 | return msg
228 | }
229 |
230 | func (p *Player) moveNormal() {
231 | p.timer++
232 | p.gameData.Update()
233 |
234 | // 移動&落下
235 | p.speed.Y += PLAYER_GRAVITY
236 | p.position.X += p.speed.X
237 | p.position.Y += p.speed.Y
238 |
239 | if p.speed.Y > PLAYER_FALL_SPEEDMAX {
240 | p.speed.Y = PLAYER_FALL_SPEEDMAX
241 | }
242 |
243 | if p.state == PLAYERSTATE_NORMAL {
244 | p.checkCollision()
245 | }
246 |
247 | // ATARI判定
248 | hitLeft := false
249 | hitRight := false
250 | hitUpper := false
251 | if p.onWall() && p.speed.Y >= 0 {
252 | if p.gameData.lunkerMode {
253 | if p.position.Y-p.jumpedPoint.Y > LUNKER_JUMP_DAMAGE1 {
254 | p.state = PLAYERSTATE_MUTEKI
255 | p.waitTimer = 0
256 | p.life -= LIFE_RATIO
257 | audio.PlaySE(audio.SE_DAMAGE)
258 | }
259 | if p.position.Y-p.jumpedPoint.Y > LUNKER_JUMP_DAMAGE2 {
260 | p.state = PLAYERSTATE_MUTEKI
261 | p.waitTimer = 0
262 | p.life -= LIFE_RATIO * 99
263 | audio.PlaySE(audio.SE_DAMAGE)
264 | }
265 | }
266 |
267 | if !input.Current().IsActionKeyPressed() || !input.Current().IsDirectionKeyPressed(input.DirectionDown) || !p.isFallable() {
268 | if p.speed.Y > 0 {
269 | p.speed.Y = 0
270 | }
271 | p.position.Y = float64(field.CHAR_SIZE * p.toFieldY())
272 | p.jumpCnt = 0
273 | }
274 |
275 | p.jumpedPoint = p.position
276 | }
277 | if p.isLeftWall() && p.speed.X < 0 {
278 | hitLeft = true
279 | }
280 | if p.isRightWall() && p.speed.X > 0 {
281 | hitRight = true
282 | }
283 | if p.isUpperWall() && p.speed.Y <= 0 {
284 | hitUpper = true
285 | }
286 |
287 | if hitUpper && !hitLeft && !hitRight {
288 | p.normalizeToUpper()
289 | }
290 | if !hitUpper && hitLeft {
291 | p.normalizeToLeft()
292 | }
293 | if !hitUpper && hitRight {
294 | p.normalizeToRight()
295 | }
296 | if hitUpper && hitRight {
297 | if p.isUpperWallBoth() {
298 | p.normalizeToUpper()
299 | } else {
300 | if p.toFieldOfsX() > p.toFieldOfsY() {
301 | p.normalizeToRight()
302 | } else {
303 | p.normalizeToUpper()
304 | }
305 | }
306 | }
307 | if hitUpper && hitLeft {
308 | if p.isUpperWallBoth() {
309 | p.normalizeToUpper()
310 | } else {
311 | if field.CHAR_SIZE-p.toFieldOfsX() > p.toFieldOfsY() {
312 | p.normalizeToLeft()
313 | } else {
314 | p.normalizeToUpper()
315 | }
316 | }
317 | }
318 |
319 | // 床特殊効果
320 | switch p.getOnField() {
321 | case fieldtype.FIELD_SCROLL_L:
322 | p.speed.X = p.speed.X*(1.0-PLAYER_GRD_ACCRATIO) + float64(p.direction*PLAYER_SPEED-SCROLLPANEL_SPEED)*PLAYER_GRD_ACCRATIO
323 | case fieldtype.FIELD_SCROLL_R:
324 | p.speed.X = p.speed.X*(1.0-PLAYER_GRD_ACCRATIO) + float64(p.direction*PLAYER_SPEED+SCROLLPANEL_SPEED)*PLAYER_GRD_ACCRATIO
325 | case fieldtype.FIELD_SLIP:
326 | // Do nothing
327 | case fieldtype.FIELD_NONE:
328 | p.speed.X = p.speed.X*(1.0-PLAYER_AIR_ACCRATIO) + float64(p.direction*PLAYER_SPEED)*PLAYER_AIR_ACCRATIO
329 | default:
330 | p.speed.X = p.speed.X*(1.0-PLAYER_GRD_ACCRATIO) + float64(p.direction*PLAYER_SPEED)*PLAYER_GRD_ACCRATIO
331 | }
332 |
333 | p.view.Update(p.position, p.speed)
334 | }
335 |
336 | func (p *Player) moveItemGet() {
337 | if p.waitTimer < WAIT_TIMER_INTERVAL {
338 | p.waitTimer++
339 | return
340 | }
341 | if input.Current().IsActionKeyJustPressed() {
342 | p.state = PLAYERSTATE_NORMAL
343 | audio.ResumeBGM(audio.BGM0)
344 | }
345 | }
346 |
347 | func (p *Player) moveByInput() {
348 | if input.Current().IsDirectionKeyPressed(input.DirectionLeft) {
349 | p.direction = -1
350 | }
351 | if input.Current().IsDirectionKeyPressed(input.DirectionRight) {
352 | p.direction = 1
353 | }
354 |
355 | if input.Current().IsActionKeyJustPressed() {
356 | if ((p.gameData.jumpMax > p.jumpCnt) || p.onWall()) && !input.Current().IsDirectionKeyPressed(input.DirectionDown) {
357 | p.speed.Y = PLAYER_JUMP // ジャンプ
358 | if !p.onWall() {
359 | p.jumpCnt++
360 | }
361 |
362 | if math.Abs(p.speed.X) < 0.1 {
363 | if p.speed.X < 0 {
364 | p.speed.X -= 0.02
365 | }
366 | if p.speed.X > 0 {
367 | p.speed.X += 0.02
368 | }
369 | }
370 | audio.PlaySE(audio.SE_JUMP)
371 | p.jumpedPoint = p.position
372 | }
373 | }
374 | }
375 |
376 | func (p *Player) checkCollision() {
377 | for xx := 0; xx < 2; xx++ {
378 | for yy := 0; yy < 2; yy++ {
379 | // アイテム獲得(STATE_ITEMGETへ遷移)
380 | if p.field.IsItem(p.toFieldX()+xx, p.toFieldY()+yy) {
381 | // 隠しアイテムは条件が必要
382 | if !p.field.IsItemGettable(p.toFieldX()+xx, p.toFieldY()+yy, p.gameData) {
383 | continue
384 | }
385 |
386 | p.state = PLAYERSTATE_ITEMGET
387 |
388 | // アイテム効果
389 | p.itemGet = p.field.GetField(p.toFieldX()+xx, p.toFieldY()+yy)
390 | switch p.field.GetField(p.toFieldX()+xx, p.toFieldY()+yy) {
391 | case fieldtype.FIELD_ITEM_POWERUP:
392 | p.gameData.jumpMax++
393 | case fieldtype.FIELD_ITEM_LIFE:
394 | p.gameData.lifeMax++
395 | p.life = p.gameData.lifeMax * LIFE_RATIO
396 | default:
397 | p.gameData.itemGetFlags[p.itemGet] = true
398 | }
399 | p.field.EraseField(p.toFieldX()+xx, p.toFieldY()+yy)
400 | p.waitTimer = 0
401 |
402 | audio.PauseBGM()
403 | if IsItemForClear(p.itemGet) || p.itemGet == fieldtype.FIELD_ITEM_POWERUP {
404 | audio.PlaySE(audio.SE_ITEMGET)
405 | } else {
406 | audio.PlaySE(audio.SE_ITEMGET2)
407 | }
408 | return
409 | }
410 | // トゲ(ダメージ)
411 | if p.field.IsSpike(p.toFieldX()+xx, p.toFieldY()+yy) {
412 | p.state = PLAYERSTATE_MUTEKI
413 | p.waitTimer = 0
414 | p.life -= LIFE_RATIO
415 | p.speed.Y = PLAYER_JUMP
416 | p.jumpCnt = -1 // ダメージ・エキストラジャンプ
417 | audio.PlaySE(audio.SE_DAMAGE)
418 | return
419 | }
420 | }
421 | }
422 | }
423 |
424 | func (p *Player) getOnField() fieldtype.FieldType {
425 | if !p.onWall() {
426 | return fieldtype.FIELD_NONE
427 | }
428 | x, y := p.toFieldX(), p.toFieldY()
429 | if p.toFieldOfsX() < field.CHAR_SIZE/2 {
430 | if p.field.IsRidable(x, y+1) {
431 | return p.field.GetField(x, y+1)
432 | }
433 | return p.field.GetField(x+1, y+1)
434 | }
435 | if p.field.IsRidable(x+1, y+1) {
436 | return p.field.GetField(x+1, y+1)
437 | }
438 | return p.field.GetField(x, y+1)
439 | }
440 |
441 | func (p *Player) drawPlayer(screen *ebiten.Image, game *Game) {
442 | v := p.view.ToScreenPosition(p.position)
443 | vx, vy := int(v.X), int(v.Y)
444 | if p.state == PLAYERSTATE_DEAD { // 死亡
445 | anime := (p.timer / 6) % 4
446 | if game.gameData.lunkerMode {
447 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*(2+anime), 128+field.CHAR_SIZE*2, field.CHAR_SIZE, field.CHAR_SIZE)
448 | return
449 | }
450 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*(2+anime), 128, field.CHAR_SIZE, field.CHAR_SIZE)
451 | return
452 | }
453 | if p.state != PLAYERSTATE_MUTEKI || p.timer%10 < 5 {
454 | anime := (p.timer / 6) % 2
455 | if !p.onWall() {
456 | anime = 0
457 | }
458 | if p.direction < 0 {
459 | if game.gameData.lunkerMode {
460 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*anime, 128+field.CHAR_SIZE*2, field.CHAR_SIZE, field.CHAR_SIZE)
461 | return
462 | }
463 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*anime, 128, field.CHAR_SIZE, field.CHAR_SIZE)
464 | return
465 | }
466 | if game.gameData.lunkerMode {
467 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*anime, 128+field.CHAR_SIZE*3, field.CHAR_SIZE, field.CHAR_SIZE)
468 | return
469 | }
470 | draw.Draw(screen, "ino", vx, vy, field.CHAR_SIZE*anime, 128+field.CHAR_SIZE, field.CHAR_SIZE, field.CHAR_SIZE)
471 | return
472 | }
473 | }
474 |
475 | func (p *Player) drawLife(screen *ebiten.Image, game *Game) {
476 | for t := 0; t < game.gameData.lifeMax; t++ {
477 | if p.life < LIFE_RATIO*2 && p.timer%10 < 5 && game.gameData.lifeMax > 1 {
478 | continue
479 | }
480 | if p.life >= (t+1)*LIFE_RATIO {
481 | draw.Draw(screen, "ino",
482 | field.CHAR_SIZE*t, 0, field.CHAR_SIZE*3, 128+field.CHAR_SIZE*1, field.CHAR_SIZE, field.CHAR_SIZE)
483 | continue
484 | }
485 | draw.Draw(screen, "ino",
486 | field.CHAR_SIZE*t, 0, field.CHAR_SIZE*4, 128+field.CHAR_SIZE*1, field.CHAR_SIZE, field.CHAR_SIZE)
487 | }
488 | }
489 |
490 | func (p *Player) drawItems(screen *ebiten.Image, game *Game) {
491 | for t := fieldtype.FIELD_ITEM_FUJI; t < fieldtype.FIELD_ITEM_MAX; t++ {
492 | if !game.gameData.itemGetFlags[t] {
493 | draw.Draw(screen, "ino",
494 | draw.ScreenWidth-field.CHAR_SIZE/4*(int(fieldtype.FIELD_ITEM_MAX)-2-int(t)), 0, // 無
495 | field.CHAR_SIZE*5, 128+field.CHAR_SIZE, field.CHAR_SIZE/4, field.CHAR_SIZE/2)
496 | continue
497 | }
498 | // クリア条件アイテムは専用グラフィック
499 | if IsItemForClear(t) {
500 | for i, c := range clearFlagItems {
501 | if c != t {
502 | continue
503 | }
504 | draw.Draw(screen, "ino",
505 | draw.ScreenWidth-field.CHAR_SIZE/4*(int(fieldtype.FIELD_ITEM_MAX)-2-int(t)), 0,
506 | field.CHAR_SIZE*5+field.CHAR_SIZE/4*(i+2), 128+field.CHAR_SIZE, field.CHAR_SIZE/4, field.CHAR_SIZE/2)
507 | }
508 | continue
509 | }
510 | draw.Draw(screen, "ino",
511 | draw.ScreenWidth-field.CHAR_SIZE/4*(int(fieldtype.FIELD_ITEM_MAX)-2-int(t)), 0, // 有
512 | field.CHAR_SIZE*5+field.CHAR_SIZE/4, 128+field.CHAR_SIZE, field.CHAR_SIZE/4, field.CHAR_SIZE/2)
513 | }
514 | }
515 |
516 | func (p *Player) drawMessage(screen *ebiten.Image, game *Game) {
517 | switch p.state {
518 | case PLAYERSTATE_ITEMGET:
519 | t := WAIT_TIMER_INTERVAL - p.waitTimer
520 | draw.DrawItemMessage(screen, p.itemGet, (draw.ScreenHeight-96)/2+24-t*t, game.lang)
521 | draw.DrawItemFrame(screen, (draw.ScreenWidth-32)/2, (draw.ScreenHeight-96)/2-t*t-24)
522 | it := int(p.itemGet) - (int(fieldtype.FIELD_ITEM_BORDER) + 1)
523 | draw.Draw(screen, "ino", (draw.ScreenWidth-16)/2, (draw.ScreenHeight-96)/2-int(t)*int(t)-16,
524 | (it%16)*field.CHAR_SIZE, (it/16+4)*field.CHAR_SIZE, field.CHAR_SIZE, field.CHAR_SIZE)
525 | case PLAYERSTATE_START:
526 | key := "msg_" + game.lang.String()
527 | draw.Draw(screen, key, (draw.ScreenWidth-256)/2, 64+(draw.ScreenHeight-240)/2, 0, 96, 256, 32)
528 | case PLAYERSTATE_DEAD:
529 | key := "msg_" + game.lang.String()
530 | draw.Draw(screen, key, (draw.ScreenWidth-256)/2, 64+(draw.ScreenHeight-240)/2, 0, 128, 256, 32)
531 | }
532 | }
533 |
534 | func (p *Player) Draw(screen *ebiten.Image, game *Game) {
535 | po := p.view.GetPosition()
536 | p.field.Draw(screen, game.gameData, int(po.X), int(po.Y))
537 | p.drawPlayer(screen, game)
538 | p.drawLife(screen, game)
539 | p.drawItems(screen, game)
540 | p.drawMessage(screen, game)
541 | }
542 |
--------------------------------------------------------------------------------
/ino/view.go:
--------------------------------------------------------------------------------
1 | package ino
2 |
3 | import (
4 | "github.com/hajimehoshi/go-inovation/ino/internal/draw"
5 | "github.com/hajimehoshi/go-inovation/ino/internal/input"
6 | )
7 |
8 | type PositionF struct {
9 | X float64
10 | Y float64
11 | }
12 |
13 | type View struct {
14 | position PositionF
15 | }
16 |
17 | func NewView(position PositionF) *View {
18 | return &View{
19 | position: position,
20 | }
21 | }
22 |
23 | func (v *View) ToScreenPosition(p PositionF) PositionF {
24 | x := p.X - v.GetPosition().X + draw.ScreenWidth/2
25 | y := p.Y - v.GetPosition().Y + draw.ScreenHeight/2
26 | return PositionF{x, y}
27 | }
28 |
29 | func (v *View) GetPosition() PositionF {
30 | p := v.position
31 | if input.Current().IsTouchEnabled() {
32 | p.Y += 16
33 | }
34 | return p
35 | }
36 |
37 | func (v *View) Update(position, speed PositionF) {
38 | const VIEW_DIRECTION_OFFSET = 30.0
39 | v.position.X = v.position.X*0.95 + (position.X+speed.X*VIEW_DIRECTION_OFFSET)*0.05
40 | v.position.Y = v.position.Y*0.95 + position.Y*0.05
41 | }
42 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "os"
7 | "runtime/pprof"
8 | "runtime/trace"
9 |
10 | "github.com/hajimehoshi/ebiten/v2"
11 | "github.com/hajimehoshi/go-inovation/ino"
12 | )
13 |
14 | var (
15 | memProfile = flag.String("memprofile", "", "write memory profile to file")
16 | traceOut = flag.String("trace", "", "write trace to file")
17 | transparent = flag.Bool("transparent", false, "background transparency")
18 | )
19 |
20 | func main() {
21 | flag.Parse()
22 |
23 | if *traceOut != "" {
24 | f, err := os.Create(*traceOut)
25 | if err != nil {
26 | panic(err)
27 | }
28 | defer f.Close()
29 |
30 | trace.Start(f)
31 | defer trace.Stop()
32 | }
33 |
34 | game, err := ino.NewGame()
35 | if err != nil {
36 | panic(err)
37 | }
38 |
39 | if *transparent {
40 | ebiten.SetScreenTransparent(true)
41 | ebiten.SetWindowDecorated(false)
42 | game.SetTransparent()
43 | }
44 |
45 | const scale = 2
46 | ebiten.SetWindowSize(ino.ScreenWidth*scale, ino.ScreenHeight*scale)
47 | ebiten.SetWindowResizable(true)
48 | if err := ebiten.RunGame(game); err != nil {
49 | panic(err)
50 | }
51 | if *memProfile != "" {
52 | f, err := os.Create(*memProfile)
53 | if err != nil {
54 | panic(err)
55 | }
56 | defer f.Close()
57 | if err := pprof.WriteHeapProfile(f); err != nil {
58 | panic(fmt.Sprintf("could not write memory profile: %s", err))
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/mobile/android/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # IntelliJ
37 | *.iml
38 | .idea/workspace.xml
39 | .idea/tasks.xml
40 | .idea/gradle.xml
41 | .idea/assetWizardSettings.xml
42 | .idea/dictionaries
43 | .idea/libraries
44 | .idea/caches
45 |
46 | # Keystore files
47 | # Uncomment the following lines if you do not want to check your keystore files in.
48 | #*.jks
49 | #*.keystore
50 |
51 | # External native build folder generated in Android Studio 2.2 and later
52 | .externalNativeBuild
53 |
54 | # Google Services (e.g. APIs or Firebase)
55 | google-services.json
56 |
57 | # Freeline
58 | freeline.py
59 | freeline/
60 | freeline_project_description.json
61 |
62 | # fastlane
63 | fastlane/report.xml
64 | fastlane/Preview.html
65 | fastlane/screenshots
66 | fastlane/test_output
67 | fastlane/readme.md
68 |
--------------------------------------------------------------------------------
/mobile/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mobile/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdk 34
5 | defaultConfig {
6 | applicationId "com.hajimehoshi.goinovation"
7 | minSdkVersion 23
8 | targetSdkVersion 34
9 | versionCode 8
10 | versionName '1.0.7'
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | productFlavors {
19 | }
20 | namespace 'com.hajimehoshi.goinovation'
21 | }
22 |
23 | dependencies {
24 | implementation fileTree(include: ['*.jar'], dir: 'libs')
25 | implementation 'androidx.appcompat:appcompat:1.7.0'
26 | implementation project(':inovation')
27 |
28 | // This line is needed to resolve a mysterious compilation error.
29 | // https://stackoverflow.com/questions/75263047/duplicate-class-in-kotlin-android
30 | implementation platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")
31 | }
32 |
--------------------------------------------------------------------------------
/mobile/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/hajimehoshi/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/java/com/hajimehoshi/goinovation/EbitenViewWithErrorHandling.java:
--------------------------------------------------------------------------------
1 | package com.hajimehoshi.goinovation;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.hajimehoshi.goinovation.mobile.EbitenView;
7 |
8 | class EbitenViewWithErrorHandling extends EbitenView {
9 | public EbitenViewWithErrorHandling(Context context) {
10 | super(context);
11 | }
12 |
13 | public EbitenViewWithErrorHandling(Context context, AttributeSet attributeSet) {
14 | super(context, attributeSet);
15 | }
16 |
17 | @Override
18 | protected void onErrorOnGameUpdate(Exception e) {
19 | // You can define your own error handling e.g., using Crashlytics.
20 | // e.g., Crashlytics.logException(e);
21 | super.onErrorOnGameUpdate(e);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/java/com/hajimehoshi/goinovation/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.hajimehoshi.goinovation;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.os.Bundle;
6 |
7 | import go.Seq;
8 |
9 | import com.hajimehoshi.goinovation.mobile.EbitenView;
10 |
11 | public class MainActivity extends AppCompatActivity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_main);
17 | Seq.setContext(getApplicationContext());
18 | }
19 |
20 | private EbitenView getEbitenView() {
21 | return (EbitenView)this.findViewById(R.id.ebitenview);
22 | }
23 |
24 | @Override
25 | protected void onPause() {
26 | super.onPause();
27 | this.getEbitenView().suspendGame();
28 | }
29 |
30 | @Override
31 | protected void onResume() {
32 | super.onResume();
33 | this.getEbitenView().resumeGame();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | いのべーしょん
3 |
4 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/mobile/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:8.2.2'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | mavenCentral()
19 | google()
20 | }
21 | }
22 |
23 | tasks.register('clean', Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/mobile/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.enableJetifier=true
20 | android.nonFinalResIds=false
21 | android.nonTransitiveRClass=false
22 | android.useAndroidX=true
--------------------------------------------------------------------------------
/mobile/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/mobile/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/mobile/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/mobile/android/inovation/build.gradle:
--------------------------------------------------------------------------------
1 | configurations.maybeCreate("default")
2 | artifacts.add("default", file('inovation.aar'))
3 |
--------------------------------------------------------------------------------
/mobile/android/mobile/build.gradle:
--------------------------------------------------------------------------------
1 | configurations.maybeCreate("default")
2 | artifacts.add("default", file('mobile.aar'))
--------------------------------------------------------------------------------
/mobile/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':inovation'
2 |
--------------------------------------------------------------------------------
/mobile/ios/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | # Pods/
38 | #
39 | # Add this line if you want to avoid checking in source code from the Xcode workspace
40 | *.xcworkspace
41 |
42 | # Carthage
43 | #
44 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
45 | # Carthage/Checkouts
46 |
47 | Carthage/Build
48 |
49 | # fastlane
50 | #
51 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
52 | # screenshots whenever they are needed.
53 | # For more information about the recommended setup visit:
54 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
55 |
56 | fastlane/report.xml
57 | fastlane/Preview.html
58 | fastlane/screenshots/**/*.png
59 | fastlane/test_output
60 |
61 | # Code Injection
62 | #
63 | # After new code Injection tools there's a generated folder /iOSInjectionProject
64 | # https://github.com/johnno1962/injectionforxcode
65 |
66 | iOSInjectionProject/
67 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8C050D3F1D16B7E500F865C4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8C050D3D1D16B7E500F865C4 /* LaunchScreen.storyboard */; };
11 | 8C319FA3232D60A90051792B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C319FA2232D60A80051792B /* AudioToolbox.framework */; };
12 | 8C341D9E22E3140400B5C749 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C341D9D22E3140400B5C749 /* OpenGLES.framework */; };
13 | 8C341DA022E3141600B5C749 /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C341D9922E313CD00B5C749 /* GLKit.framework */; };
14 | 8C4C3321271B334200CB6E83 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C4C3320271B334200CB6E83 /* GameController.framework */; };
15 | 8C7185BE1D11C56C00F98056 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C7185BD1D11C56C00F98056 /* main.m */; };
16 | 8C7185C11D11C56C00F98056 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C7185C01D11C56C00F98056 /* AppDelegate.m */; };
17 | 8C7185C71D11C56C00F98056 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8C7185C51D11C56C00F98056 /* Main.storyboard */; settings = {ASSET_TAGS = (1, ); }; };
18 | 8C7185C91D11C56C00F98056 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8C7185C81D11C56C00F98056 /* Assets.xcassets */; };
19 | 8CB110C1230972630064D8CE /* MobileEbitenViewControllerWithErrorHandling.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CB110C0230972630064D8CE /* MobileEbitenViewControllerWithErrorHandling.m */; };
20 | 8CCA2ADB2784D87000F93EF7 /* Mobile.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CCA2AD72784D18900F93EF7 /* Mobile.xcframework */; };
21 | 8CCAFF0B22E3133E00FAEDC1 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CCAFF0A22E3133E00FAEDC1 /* AVFoundation.framework */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 8C050D3E1D16B7E500F865C4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = goinovation/Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
26 | 8C319FA2232D60A80051792B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
27 | 8C341D9922E313CD00B5C749 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
28 | 8C341D9D22E3140400B5C749 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
29 | 8C4C3320271B334200CB6E83 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
30 | 8C7185B91D11C56C00F98056 /* goinovation.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = goinovation.app; sourceTree = BUILT_PRODUCTS_DIR; };
31 | 8C7185BD1D11C56C00F98056 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
32 | 8C7185BF1D11C56C00F98056 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
33 | 8C7185C01D11C56C00F98056 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
34 | 8C7185C61D11C56C00F98056 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
35 | 8C7185C81D11C56C00F98056 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
36 | 8C7185CD1D11C56C00F98056 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
37 | 8CB110C0230972630064D8CE /* MobileEbitenViewControllerWithErrorHandling.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MobileEbitenViewControllerWithErrorHandling.m; sourceTree = ""; };
38 | 8CB110C22309728C0064D8CE /* MobileEbitenViewControllerWithErrorHandling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MobileEbitenViewControllerWithErrorHandling.h; sourceTree = ""; };
39 | 8CCA2AD72784D18900F93EF7 /* Mobile.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Mobile.xcframework; sourceTree = ""; };
40 | 8CCAFF0A22E3133E00FAEDC1 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
41 | /* End PBXFileReference section */
42 |
43 | /* Begin PBXFrameworksBuildPhase section */
44 | 8C7185B61D11C56C00F98056 /* Frameworks */ = {
45 | isa = PBXFrameworksBuildPhase;
46 | buildActionMask = 2147483647;
47 | files = (
48 | 8C319FA3232D60A90051792B /* AudioToolbox.framework in Frameworks */,
49 | 8C341DA022E3141600B5C749 /* GLKit.framework in Frameworks */,
50 | 8C4C3321271B334200CB6E83 /* GameController.framework in Frameworks */,
51 | 8C341D9E22E3140400B5C749 /* OpenGLES.framework in Frameworks */,
52 | 8CCAFF0B22E3133E00FAEDC1 /* AVFoundation.framework in Frameworks */,
53 | 8CCA2ADB2784D87000F93EF7 /* Mobile.xcframework in Frameworks */,
54 | );
55 | runOnlyForDeploymentPostprocessing = 0;
56 | };
57 | /* End PBXFrameworksBuildPhase section */
58 |
59 | /* Begin PBXGroup section */
60 | 8C7185B01D11C56C00F98056 = {
61 | isa = PBXGroup;
62 | children = (
63 | 8C7185BB1D11C56C00F98056 /* goinovation */,
64 | 8C7185BA1D11C56C00F98056 /* Products */,
65 | 8CCAFF0922E3133E00FAEDC1 /* Frameworks */,
66 | );
67 | sourceTree = "";
68 | };
69 | 8C7185BA1D11C56C00F98056 /* Products */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 8C7185B91D11C56C00F98056 /* goinovation.app */,
73 | );
74 | name = Products;
75 | sourceTree = "";
76 | };
77 | 8C7185BB1D11C56C00F98056 /* goinovation */ = {
78 | isa = PBXGroup;
79 | children = (
80 | 8C7185BF1D11C56C00F98056 /* AppDelegate.h */,
81 | 8C7185C01D11C56C00F98056 /* AppDelegate.m */,
82 | 8CB110C22309728C0064D8CE /* MobileEbitenViewControllerWithErrorHandling.h */,
83 | 8CB110C0230972630064D8CE /* MobileEbitenViewControllerWithErrorHandling.m */,
84 | 8C7185C51D11C56C00F98056 /* Main.storyboard */,
85 | 8C050D3D1D16B7E500F865C4 /* LaunchScreen.storyboard */,
86 | 8C7185C81D11C56C00F98056 /* Assets.xcassets */,
87 | 8C7185CD1D11C56C00F98056 /* Info.plist */,
88 | 8C7185BC1D11C56C00F98056 /* Supporting Files */,
89 | );
90 | path = goinovation;
91 | sourceTree = "";
92 | };
93 | 8C7185BC1D11C56C00F98056 /* Supporting Files */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 8C7185BD1D11C56C00F98056 /* main.m */,
97 | );
98 | name = "Supporting Files";
99 | sourceTree = "";
100 | };
101 | 8CCAFF0922E3133E00FAEDC1 /* Frameworks */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 8CCA2AD72784D18900F93EF7 /* Mobile.xcframework */,
105 | 8C4C3320271B334200CB6E83 /* GameController.framework */,
106 | 8C319FA2232D60A80051792B /* AudioToolbox.framework */,
107 | 8C341D9D22E3140400B5C749 /* OpenGLES.framework */,
108 | 8C341D9922E313CD00B5C749 /* GLKit.framework */,
109 | 8CCAFF0A22E3133E00FAEDC1 /* AVFoundation.framework */,
110 | );
111 | name = Frameworks;
112 | sourceTree = "";
113 | };
114 | /* End PBXGroup section */
115 |
116 | /* Begin PBXNativeTarget section */
117 | 8C7185B81D11C56C00F98056 /* goinovation */ = {
118 | isa = PBXNativeTarget;
119 | buildConfigurationList = 8C7185D01D11C56C00F98056 /* Build configuration list for PBXNativeTarget "goinovation" */;
120 | buildPhases = (
121 | 8C7185B51D11C56C00F98056 /* Sources */,
122 | 8C7185B61D11C56C00F98056 /* Frameworks */,
123 | 8C7185B71D11C56C00F98056 /* Resources */,
124 | );
125 | buildRules = (
126 | );
127 | dependencies = (
128 | );
129 | name = goinovation;
130 | productName = goinovation;
131 | productReference = 8C7185B91D11C56C00F98056 /* goinovation.app */;
132 | productType = "com.apple.product-type.application";
133 | };
134 | /* End PBXNativeTarget section */
135 |
136 | /* Begin PBXProject section */
137 | 8C7185B11D11C56C00F98056 /* Project object */ = {
138 | isa = PBXProject;
139 | attributes = {
140 | KnownAssetTags = (
141 | 1,
142 | );
143 | LastUpgradeCheck = 1320;
144 | ORGANIZATIONNAME = "Hajime Hoshi";
145 | TargetAttributes = {
146 | 8C7185B81D11C56C00F98056 = {
147 | CreatedOnToolsVersion = 7.3.1;
148 | DevelopmentTeam = M89F6KFPW7;
149 | ProvisioningStyle = Automatic;
150 | };
151 | };
152 | };
153 | buildConfigurationList = 8C7185B41D11C56C00F98056 /* Build configuration list for PBXProject "goinovation" */;
154 | compatibilityVersion = "Xcode 3.2";
155 | developmentRegion = English;
156 | hasScannedForEncodings = 0;
157 | knownRegions = (
158 | English,
159 | en,
160 | Base,
161 | );
162 | mainGroup = 8C7185B01D11C56C00F98056;
163 | productRefGroup = 8C7185BA1D11C56C00F98056 /* Products */;
164 | projectDirPath = "";
165 | projectRoot = "";
166 | targets = (
167 | 8C7185B81D11C56C00F98056 /* goinovation */,
168 | );
169 | };
170 | /* End PBXProject section */
171 |
172 | /* Begin PBXResourcesBuildPhase section */
173 | 8C7185B71D11C56C00F98056 /* Resources */ = {
174 | isa = PBXResourcesBuildPhase;
175 | buildActionMask = 2147483647;
176 | files = (
177 | 8C050D3F1D16B7E500F865C4 /* LaunchScreen.storyboard in Resources */,
178 | 8C7185C91D11C56C00F98056 /* Assets.xcassets in Resources */,
179 | 8C7185C71D11C56C00F98056 /* Main.storyboard in Resources */,
180 | );
181 | runOnlyForDeploymentPostprocessing = 0;
182 | };
183 | /* End PBXResourcesBuildPhase section */
184 |
185 | /* Begin PBXSourcesBuildPhase section */
186 | 8C7185B51D11C56C00F98056 /* Sources */ = {
187 | isa = PBXSourcesBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | 8CB110C1230972630064D8CE /* MobileEbitenViewControllerWithErrorHandling.m in Sources */,
191 | 8C7185C11D11C56C00F98056 /* AppDelegate.m in Sources */,
192 | 8C7185BE1D11C56C00F98056 /* main.m in Sources */,
193 | );
194 | runOnlyForDeploymentPostprocessing = 0;
195 | };
196 | /* End PBXSourcesBuildPhase section */
197 |
198 | /* Begin PBXVariantGroup section */
199 | 8C050D3D1D16B7E500F865C4 /* LaunchScreen.storyboard */ = {
200 | isa = PBXVariantGroup;
201 | children = (
202 | 8C050D3E1D16B7E500F865C4 /* Base */,
203 | );
204 | name = LaunchScreen.storyboard;
205 | path = ..;
206 | sourceTree = "";
207 | };
208 | 8C7185C51D11C56C00F98056 /* Main.storyboard */ = {
209 | isa = PBXVariantGroup;
210 | children = (
211 | 8C7185C61D11C56C00F98056 /* Base */,
212 | );
213 | name = Main.storyboard;
214 | sourceTree = "";
215 | };
216 | /* End PBXVariantGroup section */
217 |
218 | /* Begin XCBuildConfiguration section */
219 | 8C7185CE1D11C56C00F98056 /* Debug */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | ALWAYS_SEARCH_USER_PATHS = NO;
223 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
224 | CLANG_ANALYZER_NONNULL = YES;
225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
226 | CLANG_CXX_LIBRARY = "libc++";
227 | CLANG_ENABLE_MODULES = YES;
228 | CLANG_ENABLE_OBJC_ARC = YES;
229 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
230 | CLANG_WARN_BOOL_CONVERSION = YES;
231 | CLANG_WARN_COMMA = YES;
232 | CLANG_WARN_CONSTANT_CONVERSION = YES;
233 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
234 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
235 | CLANG_WARN_EMPTY_BODY = YES;
236 | CLANG_WARN_ENUM_CONVERSION = YES;
237 | CLANG_WARN_INFINITE_RECURSION = YES;
238 | CLANG_WARN_INT_CONVERSION = YES;
239 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
240 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
241 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
242 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
243 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
244 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
245 | CLANG_WARN_STRICT_PROTOTYPES = YES;
246 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
247 | CLANG_WARN_UNREACHABLE_CODE = YES;
248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
249 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
250 | COPY_PHASE_STRIP = NO;
251 | DEBUG_INFORMATION_FORMAT = dwarf;
252 | ENABLE_STRICT_OBJC_MSGSEND = YES;
253 | ENABLE_TESTABILITY = YES;
254 | GCC_C_LANGUAGE_STANDARD = gnu99;
255 | GCC_DYNAMIC_NO_PIC = NO;
256 | GCC_NO_COMMON_BLOCKS = YES;
257 | GCC_OPTIMIZATION_LEVEL = 0;
258 | GCC_PREPROCESSOR_DEFINITIONS = (
259 | "DEBUG=1",
260 | "$(inherited)",
261 | );
262 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
263 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
264 | GCC_WARN_UNDECLARED_SELECTOR = YES;
265 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
266 | GCC_WARN_UNUSED_FUNCTION = YES;
267 | GCC_WARN_UNUSED_VARIABLE = YES;
268 | HEADER_SEARCH_PATHS = "";
269 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
270 | MTL_ENABLE_DEBUG_INFO = YES;
271 | ONLY_ACTIVE_ARCH = YES;
272 | SDKROOT = iphoneos;
273 | };
274 | name = Debug;
275 | };
276 | 8C7185CF1D11C56C00F98056 /* Release */ = {
277 | isa = XCBuildConfiguration;
278 | buildSettings = {
279 | ALWAYS_SEARCH_USER_PATHS = NO;
280 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
281 | CLANG_ANALYZER_NONNULL = YES;
282 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
283 | CLANG_CXX_LIBRARY = "libc++";
284 | CLANG_ENABLE_MODULES = YES;
285 | CLANG_ENABLE_OBJC_ARC = YES;
286 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
287 | CLANG_WARN_BOOL_CONVERSION = YES;
288 | CLANG_WARN_COMMA = YES;
289 | CLANG_WARN_CONSTANT_CONVERSION = YES;
290 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
291 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
292 | CLANG_WARN_EMPTY_BODY = YES;
293 | CLANG_WARN_ENUM_CONVERSION = YES;
294 | CLANG_WARN_INFINITE_RECURSION = YES;
295 | CLANG_WARN_INT_CONVERSION = YES;
296 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
297 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
298 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
300 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
302 | CLANG_WARN_STRICT_PROTOTYPES = YES;
303 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
304 | CLANG_WARN_UNREACHABLE_CODE = YES;
305 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
306 | CODE_SIGN_IDENTITY = "iPhone Distribution";
307 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
308 | COPY_PHASE_STRIP = NO;
309 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
310 | ENABLE_NS_ASSERTIONS = NO;
311 | ENABLE_STRICT_OBJC_MSGSEND = YES;
312 | GCC_C_LANGUAGE_STANDARD = gnu99;
313 | GCC_NO_COMMON_BLOCKS = YES;
314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
316 | GCC_WARN_UNDECLARED_SELECTOR = YES;
317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
318 | GCC_WARN_UNUSED_FUNCTION = YES;
319 | GCC_WARN_UNUSED_VARIABLE = YES;
320 | HEADER_SEARCH_PATHS = "";
321 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
322 | MTL_ENABLE_DEBUG_INFO = NO;
323 | PROVISIONING_PROFILE = "";
324 | SDKROOT = iphoneos;
325 | VALIDATE_PRODUCT = YES;
326 | };
327 | name = Release;
328 | };
329 | 8C7185D11D11C56C00F98056 /* Debug */ = {
330 | isa = XCBuildConfiguration;
331 | buildSettings = {
332 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
333 | CODE_SIGN_IDENTITY = "Apple Development";
334 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
335 | CODE_SIGN_STYLE = Automatic;
336 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
337 | DEVELOPMENT_TEAM = M89F6KFPW7;
338 | ENABLE_BITCODE = NO;
339 | FRAMEWORK_SEARCH_PATHS = (
340 | "$(inherited)",
341 | "$(PROJECT_DIR)",
342 | );
343 | HEADER_SEARCH_PATHS = "";
344 | INFOPLIST_FILE = goinovation/Info.plist;
345 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
346 | LD_RUNPATH_SEARCH_PATHS = (
347 | "$(inherited)",
348 | "@executable_path/Frameworks",
349 | );
350 | PRODUCT_BUNDLE_IDENTIFIER = com.hajimehoshi.goinovation;
351 | PRODUCT_NAME = "$(TARGET_NAME)";
352 | PROVISIONING_PROFILE_SPECIFIER = "";
353 | TARGETED_DEVICE_FAMILY = "1,2";
354 | };
355 | name = Debug;
356 | };
357 | 8C7185D21D11C56C00F98056 /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
361 | CODE_SIGN_IDENTITY = "iPhone Distribution: Hajime Hoshi (M89F6KFPW7)";
362 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Hajime Hoshi (M89F6KFPW7)";
363 | DEVELOPMENT_TEAM = M89F6KFPW7;
364 | ENABLE_BITCODE = NO;
365 | FRAMEWORK_SEARCH_PATHS = (
366 | "$(inherited)",
367 | "$(PROJECT_DIR)",
368 | );
369 | HEADER_SEARCH_PATHS = "";
370 | INFOPLIST_FILE = goinovation/Info.plist;
371 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
372 | LD_RUNPATH_SEARCH_PATHS = (
373 | "$(inherited)",
374 | "@executable_path/Frameworks",
375 | );
376 | PRODUCT_BUNDLE_IDENTIFIER = com.hajimehoshi.goinovation;
377 | PRODUCT_NAME = "$(TARGET_NAME)";
378 | PROVISIONING_PROFILE_SPECIFIER = "iOS Dev";
379 | TARGETED_DEVICE_FAMILY = "1,2";
380 | };
381 | name = Release;
382 | };
383 | /* End XCBuildConfiguration section */
384 |
385 | /* Begin XCConfigurationList section */
386 | 8C7185B41D11C56C00F98056 /* Build configuration list for PBXProject "goinovation" */ = {
387 | isa = XCConfigurationList;
388 | buildConfigurations = (
389 | 8C7185CE1D11C56C00F98056 /* Debug */,
390 | 8C7185CF1D11C56C00F98056 /* Release */,
391 | );
392 | defaultConfigurationIsVisible = 0;
393 | defaultConfigurationName = Release;
394 | };
395 | 8C7185D01D11C56C00F98056 /* Build configuration list for PBXNativeTarget "goinovation" */ = {
396 | isa = XCConfigurationList;
397 | buildConfigurations = (
398 | 8C7185D11D11C56C00F98056 /* Debug */,
399 | 8C7185D21D11C56C00F98056 /* Release */,
400 | );
401 | defaultConfigurationIsVisible = 0;
402 | defaultConfigurationName = Release;
403 | };
404 | /* End XCConfigurationList section */
405 | };
406 | rootObject = 8C7185B11D11C56C00F98056 /* Project object */;
407 | }
408 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // goinovation
4 | //
5 | // Created by Hajime Hoshi on 6/16/16.
6 | // Copyright © 2016 Hajime Hoshi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // goinovation
4 | //
5 | // Created by Hajime Hoshi on 6/16/16.
6 | // Copyright © 2016 Hajime Hoshi. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | #import "MobileEbitenViewControllerWithErrorHandling.h"
12 |
13 | @interface AppDelegate ()
14 |
15 | @end
16 |
17 | @implementation AppDelegate
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 | // Override point for customization after application launch.
21 | return YES;
22 | }
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
27 | [[self ebitenViewContrller] suspendGame];
28 | }
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 | - (void)applicationWillEnterForeground:(UIApplication *)application {
36 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
37 | }
38 |
39 | - (void)applicationDidBecomeActive:(UIApplication *)application {
40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
41 | [[self ebitenViewContrller] resumeGame];
42 | }
43 |
44 | - (void)applicationWillTerminate:(UIApplication *)application {
45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
46 | }
47 |
48 | - (MobileEbitenViewControllerWithErrorHandling*)ebitenViewContrller
49 | {
50 | return (MobileEbitenViewControllerWithErrorHandling*)([[self window] rootViewController]);
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "size" : "29x29",
15 | "idiom" : "iphone",
16 | "filename" : "icon58.png",
17 | "scale" : "2x"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "iphone",
22 | "filename" : "icon87.png",
23 | "scale" : "3x"
24 | },
25 | {
26 | "size" : "40x40",
27 | "idiom" : "iphone",
28 | "filename" : "icon80.png",
29 | "scale" : "2x"
30 | },
31 | {
32 | "size" : "40x40",
33 | "idiom" : "iphone",
34 | "filename" : "icon120.png",
35 | "scale" : "3x"
36 | },
37 | {
38 | "size" : "60x60",
39 | "idiom" : "iphone",
40 | "filename" : "icon120-1.png",
41 | "scale" : "2x"
42 | },
43 | {
44 | "size" : "60x60",
45 | "idiom" : "iphone",
46 | "filename" : "icon180.png",
47 | "scale" : "3x"
48 | },
49 | {
50 | "size" : "1024x1024",
51 | "idiom" : "ios-marketing",
52 | "filename" : "icon1024.png",
53 | "scale" : "1x"
54 | }
55 | ],
56 | "info" : {
57 | "version" : 1,
58 | "author" : "xcode"
59 | }
60 | }
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon1024.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon120-1.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon120.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon180.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon58.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon80.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/mobile/ios/goinovation/Assets.xcassets/AppIcon.appiconset/icon87.png
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | いのべーしょん
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0.5
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 6
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/MobileEbitenViewControllerWithErrorHandling.h:
--------------------------------------------------------------------------------
1 | //
2 | // MobileEbitenViewWithErrorHandling.h
3 | // goinovation
4 | //
5 | // Created by Hajime Hoshi on 2019/08/18.
6 | // Copyright © 2019 Hajime Hoshi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MobileEbitenViewControllerWithErrorHandling : MobileEbitenViewController
12 | @end
13 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/MobileEbitenViewControllerWithErrorHandling.m:
--------------------------------------------------------------------------------
1 | //
2 | // MobileEbitenViewWithErrorHandling.m
3 | // goinovation
4 | //
5 | // Created by Hajime Hoshi on 2019/08/18.
6 | // Copyright © 2019 Hajime Hoshi. All rights reserved.
7 | //
8 |
9 | #import "MobileEbitenViewControllerWithErrorHandling.h"
10 |
11 | #import
12 |
13 | @implementation MobileEbitenViewControllerWithErrorHandling {
14 | }
15 |
16 | - (void)onErrorOnGameUpdate:(NSError*)err {
17 | // You can define your own error handling e.g., using Crashlytics.
18 | NSLog(@"Inovation Error!: %@", err);
19 | }
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/mobile/ios/goinovation/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // goinovation
4 | //
5 | // Created by Hajime Hoshi on 6/16/16.
6 | // Copyright © 2016 Hajime Hoshi. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/mobile/mobile.go:
--------------------------------------------------------------------------------
1 | package mobile
2 |
3 | import (
4 | "github.com/hajimehoshi/ebiten/v2/mobile"
5 |
6 | "github.com/hajimehoshi/go-inovation/ino"
7 | )
8 |
9 | func init() {
10 | inogame, err := ino.NewGame()
11 | if err != nil {
12 | panic(err)
13 | }
14 | mobile.SetGame(inogame)
15 | }
16 |
17 | // Dummy is a dummy exported function.
18 | //
19 | // gomobile doesn't compile a package that doesn't include any exported function.
20 | // Dummy forces gomobile to compile this package.
21 | func Dummy() {}
22 |
--------------------------------------------------------------------------------
/notarize_app.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | name=innovation2007
4 | app_name=Innovation2007.app
5 | bundle_id=com.hajimehoshi.innovation2007.macos
6 | email=hajimehoshi@gmail.com
7 |
8 | # Specify a 'Developer ID' (Developer ID Application) certificate.
9 | # See https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/resolving_common_notarization_issues
10 | developer_name='Developer ID Application: Hajime Hoshi (M89F6KFPW7)'
11 |
12 | # To get the provider, run `xcrun altool --list-providers --username= --password=` and see the ProviderShortname.
13 | asc_provider=M89F6KFPW7
14 |
15 | # macOS: signing
16 | # See
17 | # * https://partner.steamgames.com/doc/store/application/platforms
18 | # * https://coldandold.com/posts/releasing-steam-game-on-mac/
19 |
20 | cd bin
21 | mkdir -p .cache
22 |
23 | echo '
24 |
25 |
26 |
27 | com.apple.security.cs.disable-library-validation
28 |
29 | com.apple.security.cs.allow-dyld-environment-variables
30 |
31 |
32 | ' > .cache/entitlements.plist
33 |
34 | codesign --display \
35 | --verbose \
36 | --verify \
37 | --sign "${developer_name}" \
38 | --timestamp \
39 | --options runtime \
40 | --force \
41 | --entitlements .cache/entitlements.plist \
42 | --deep \
43 | ${app_name}
44 |
45 | ditto -c -k --keepParent ${app_name} ${app_name}.zip
46 |
47 | if [[ -z "${APP_PASSWORD}" ]]; then
48 | echo 'fail: set APP_PASSWORD. See https://support.apple.com/en-us/HT204397'
49 | exit 1
50 | fi
51 |
52 | xcrun altool --notarize-app \
53 | --primary-bundle-id "${bundle_id}" \
54 | --username "${email}" \
55 | --password "${APP_PASSWORD}" \
56 | --asc-provider "${asc_provider}" \
57 | --file ${app_name}.zip
58 | rm ${app_name}.zip
59 |
60 | echo "Please wait for an email from Apple."
61 | echo "For the log, run this command: xcrun altool --notarization-info --username --password "
62 | echo "After the notarization succeeds, run this command: xcrun stapler staple bin/${app_name}"
63 |
--------------------------------------------------------------------------------
/steam/community_capsule_184x69_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/community_capsule_184x69_english.png
--------------------------------------------------------------------------------
/steam/community_capsule_184x69_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/community_capsule_184x69_japanese.png
--------------------------------------------------------------------------------
/steam/icon/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_128x128.png
--------------------------------------------------------------------------------
/steam/icon/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_16x16.png
--------------------------------------------------------------------------------
/steam/icon/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_256x256.png
--------------------------------------------------------------------------------
/steam/icon/icon_32x32.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_32x32.ico
--------------------------------------------------------------------------------
/steam/icon/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_32x32.png
--------------------------------------------------------------------------------
/steam/icon/icon_512x512.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_512x512.icns
--------------------------------------------------------------------------------
/steam/icon/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_512x512.png
--------------------------------------------------------------------------------
/steam/icon/icon_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/icon/icon_64x64.png
--------------------------------------------------------------------------------
/steam/library_capsule_600x900_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_capsule_600x900_english.png
--------------------------------------------------------------------------------
/steam/library_capsule_600x900_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_capsule_600x900_japanese.png
--------------------------------------------------------------------------------
/steam/library_hero_3840x1240_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_hero_3840x1240_english.png
--------------------------------------------------------------------------------
/steam/library_hero_3840x1240_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_hero_3840x1240_japanese.png
--------------------------------------------------------------------------------
/steam/library_logo_1280x720_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_logo_1280x720_english.png
--------------------------------------------------------------------------------
/steam/library_logo_1280x720_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/library_logo_1280x720_japanese.png
--------------------------------------------------------------------------------
/steam/msg_en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/msg_en.png
--------------------------------------------------------------------------------
/steam/msg_ja.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/msg_ja.png
--------------------------------------------------------------------------------
/steam/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot.png
--------------------------------------------------------------------------------
/steam/screenshot/convert.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "image/color"
7 | "image/png"
8 | "math"
9 | "os"
10 | "regexp"
11 |
12 | "github.com/hajimehoshi/ebiten/v2"
13 | "github.com/hajimehoshi/ebiten/v2/ebitenutil"
14 | )
15 |
16 | var regularTermination = errors.New("regular termiination")
17 |
18 | var reFilename = regexp.MustCompile(`^screenshot([^_]+)_([a-z]+)\.png$`)
19 |
20 | type Game struct {
21 | tmpImage *ebiten.Image
22 | }
23 |
24 | func (g *Game) getTmpImage(width, height int) *ebiten.Image {
25 | if g.tmpImage != nil {
26 | if w, h := g.tmpImage.Size(); w == width && h == height {
27 | g.tmpImage.Clear()
28 | return g.tmpImage
29 | }
30 | }
31 | g.tmpImage = ebiten.NewImage(width, height)
32 | return g.tmpImage
33 | }
34 |
35 | func (g *Game) Update() error {
36 | ents, err := os.ReadDir(".")
37 | if err != nil {
38 | return err
39 | }
40 |
41 | const (
42 | screenshotWidth = 1920
43 | screenshotHeight = 1080
44 | )
45 |
46 | offscreen := ebiten.NewImage(screenshotWidth, screenshotHeight)
47 | for _, ent := range ents {
48 | if ent.IsDir() {
49 | continue
50 | }
51 | name := ent.Name()
52 | m := reFilename.FindStringSubmatch(name)
53 | if m == nil {
54 | continue
55 | }
56 |
57 | img, _, err := ebitenutil.NewImageFromFile(name)
58 | if err != nil {
59 | return err
60 | }
61 |
62 | w, h := img.Size()
63 | scale := screenshotHeight / float64(h)
64 | iscale := math.Ceil(scale)
65 | op := &ebiten.DrawImageOptions{}
66 | op.GeoM.Scale(iscale, iscale)
67 | tmpImg := g.getTmpImage(w * int(iscale), h * int(iscale))
68 | tmpImg.DrawImage(img, op)
69 |
70 | op = &ebiten.DrawImageOptions{}
71 | op.GeoM.Scale(float64(scale) / float64(iscale), float64(scale) / float64(iscale))
72 | op.GeoM.Translate((screenshotWidth - float64(w) * scale) / 2, 0)
73 | op.Filter = ebiten.FilterLinear
74 | offscreen.Clear()
75 | offscreen.Fill(color.Black)
76 | offscreen.DrawImage(tmpImg, op)
77 |
78 | newName := fmt.Sprintf("screenshot%s_%dx%d_%s.png", m[1], screenshotWidth, screenshotHeight, m[2])
79 | f, err := os.Create(newName)
80 | if err != nil {
81 | return err
82 | }
83 | defer f.Close()
84 | if err := png.Encode(f, offscreen); err != nil {
85 | return err
86 | }
87 | }
88 | return regularTermination
89 | }
90 |
91 | func (*Game) Draw(screen *ebiten.Image) {
92 | }
93 |
94 | func (*Game) Layout(width, height int) (int, int) {
95 | return width, height
96 | }
97 |
98 | func main() {
99 | ebiten.SetWindowDecorated(false)
100 | ebiten.SetScreenTransparent(true)
101 | if err := ebiten.RunGame(&Game{}); err != nil && err != regularTermination {
102 | panic(err)
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/steam/screenshot/screenshot3_1920x1080_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot3_1920x1080_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot3_1920x1080_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot3_1920x1080_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot3_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot3_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot3_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot3_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot4_1920x1080_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot4_1920x1080_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot4_1920x1080_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot4_1920x1080_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot4_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot4_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot4_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot4_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot5_1920x1080_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot5_1920x1080_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot5_1920x1080_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot5_1920x1080_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot5_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot5_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot5_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot5_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot6_1920x1080_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot6_1920x1080_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot6_1920x1080_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot6_1920x1080_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot6_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot6_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot6_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot6_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot7_1920x1080_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot7_1920x1080_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot7_1920x1080_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot7_1920x1080_japanese.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot7_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot7_english.png
--------------------------------------------------------------------------------
/steam/screenshot/screenshot7_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/screenshot/screenshot7_japanese.png
--------------------------------------------------------------------------------
/steam/store_header_capsule_460x215_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_header_capsule_460x215_english.png
--------------------------------------------------------------------------------
/steam/store_header_capsule_460x215_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_header_capsule_460x215_japanese.png
--------------------------------------------------------------------------------
/steam/store_main_capsule_616x353_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_main_capsule_616x353_english.png
--------------------------------------------------------------------------------
/steam/store_main_capsule_616x353_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_main_capsule_616x353_japanese.png
--------------------------------------------------------------------------------
/steam/store_small_capsule_231x87_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_small_capsule_231x87_english.png
--------------------------------------------------------------------------------
/steam/store_small_capsule_231x87_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_small_capsule_231x87_japanese.png
--------------------------------------------------------------------------------
/steam/store_vertical_capsule_374x448_english.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_vertical_capsule_374x448_english.png
--------------------------------------------------------------------------------
/steam/store_vertical_capsule_374x448_japanese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/store_vertical_capsule_374x448_japanese.png
--------------------------------------------------------------------------------
/steam/title_en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/title_en.png
--------------------------------------------------------------------------------
/steam/title_ja.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hajimehoshi/go-inovation/20ee4c8e276f04cf0ba715aa938f6afa10e334d9/steam/title_ja.png
--------------------------------------------------------------------------------
/steambuild_darwin.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | name=innovation2007
4 | app_name=Innovation2007.app
5 | bundle_id=com.hajimehoshi.innovation2007.macos
6 | mkdir -p bin
7 |
8 | rm -rf bin/${app_name}
9 | mkdir -p bin/${app_name}/Contents/MacOS
10 | mkdir -p bin/${app_name}/Contents/Resources
11 | env CGO_ENABLED=1 CGO_CFLAGS=-mmacosx-version-min=10.12 CGO_LDFLAGS=-mmacosx-version-min=10.12 GOARCH=amd64 go build -tags=steam -o bin/${app_name}/Contents/MacOS/${name} .
12 | cp steam/icon/icon_512x512.icns bin/${app_name}/Contents/Resources/icon.icns
13 | echo '
14 |
15 |
16 |
17 | CFBundlePackageType
18 | APPL
19 | CFBundleInfoDictionaryVersion
20 | 6.0
21 | CFBundleExecutable
22 | {{.Name}}
23 | CFBundleIdentifier
24 | {{.BundleID}}
25 | CFBundleIconFile
26 | icon.icns
27 | CFBundleVersion
28 | 0.0.0
29 | CFBundleShortVersionString
30 | 0.0.0
31 | NSHighResolutionCapable
32 |
33 | LSMinimumSystemVersion
34 | 10.12.0
35 |
36 | ' |
37 | sed -e "s/{{.Name}}/${name}/g" |
38 | sed -e "s/{{.BundleID}}/${bundle_id}/g" > bin/${app_name}/Contents/Info.plist
39 | # Note: In order to open the *.app, steam_appid.txt should be copied to *.app/Contents/Resources.
40 | # However, this file should not be copied when you submit the app.
41 |
--------------------------------------------------------------------------------
/steambuild_linux.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | name=innovation2007
4 | STEAM_RUNTIME_VERSION=0.20210817.0
5 | GO_VERSION=$(go env GOVERSION)
6 |
7 | cd bin
8 |
9 | mkdir -p .cache/${STEAM_RUNTIME_VERSION}
10 |
11 | # Download binaries for 386.
12 | if [[ ! -f .cache/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-i386-scout-sysroot.Dockerfile ]]; then
13 | (cd .cache/${STEAM_RUNTIME_VERSION}; curl --location --remote-name https://repo.steampowered.com/steamrt-images-scout/snapshots/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-i386-scout-sysroot.Dockerfile)
14 | fi
15 | if [[ ! -f .cache/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-i386-scout-sysroot.tar.gz ]]; then
16 | (cd .cache/${STEAM_RUNTIME_VERSION}; curl --location --remote-name https://repo.steampowered.com/steamrt-images-scout/snapshots/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-i386-scout-sysroot.tar.gz)
17 | fi
18 | if [[ ! -f .cache/${GO_VERSION}.linux-386.tar.gz ]]; then
19 | (cd .cache; curl --location --remote-name https://golang.org/dl/${GO_VERSION}.linux-386.tar.gz)
20 | fi
21 |
22 | # Download binaries for amd64.
23 | if [[ ! -f .cache/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-scout-sysroot.Dockerfile ]]; then
24 | (cd .cache/${STEAM_RUNTIME_VERSION}; curl --location --remote-name https://repo.steampowered.com/steamrt-images-scout/snapshots/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-scout-sysroot.Dockerfile)
25 | fi
26 | if [[ ! -f .cache/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-scout-sysroot.tar.gz ]]; then
27 | (cd .cache/${STEAM_RUNTIME_VERSION}; curl --location --remote-name https://repo.steampowered.com/steamrt-images-scout/snapshots/${STEAM_RUNTIME_VERSION}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-scout-sysroot.tar.gz)
28 | fi
29 | if [[ ! -f .cache/${GO_VERSION}.linux-amd64.tar.gz ]]; then
30 | (cd .cache; curl --location --remote-name https://golang.org/dl/${GO_VERSION}.linux-amd64.tar.gz)
31 | fi
32 |
33 | # Build for 386
34 | (cd .cache/${STEAM_RUNTIME_VERSION}; docker build -f com.valvesoftware.SteamRuntime.Sdk-i386-scout-sysroot.Dockerfile -t steamrt_scout_i386:latest .)
35 | docker run --rm --workdir=/work --volume $(pwd)/..:/work steamrt_scout_i386:latest /bin/sh -c "
36 | export PATH=\$PATH:/usr/local/go/bin
37 | export CGO_CFLAGS=-std=gnu99
38 |
39 | rm -rf /usr/local/go && tar -C /usr/local -xzf bin/.cache/${GO_VERSION}.linux-386.tar.gz
40 |
41 | go build -tags=steam -o bin/${name}_linux_386 .
42 | "
43 |
44 | # Build for amd64
45 | (cd .cache/${STEAM_RUNTIME_VERSION}; docker build -f com.valvesoftware.SteamRuntime.Sdk-amd64,i386-scout-sysroot.Dockerfile -t steamrt_scout_amd64:latest .)
46 | docker run --rm --workdir=/work --volume $(pwd)/..:/work steamrt_scout_amd64:latest /bin/sh -c "
47 | export PATH=\$PATH:/usr/local/go/bin
48 | export CGO_CFLAGS=-std=gnu99
49 |
50 | rm -rf /usr/local/go && tar -C /usr/local -xzf bin/.cache/${GO_VERSION}.linux-amd64.tar.gz
51 |
52 | go build -tags=steam -o bin/${name}_linux_amd64 .
53 | "
54 |
--------------------------------------------------------------------------------
/steambuild_windows.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | name=innovation2007
4 | mkdir -p bin
5 |
6 | # TODO: Should '-ldflags=-H=windowsgui' be added?
7 | GOOS=windows GOARCH=386 go build -tags=steam -o bin/${name}_windows_386.exe .
8 | GOOS=windows GOARCH=amd64 go build -tags=steam -o bin/${name}_windows_amd64.exe .
9 |
--------------------------------------------------------------------------------
/tools.go:
--------------------------------------------------------------------------------
1 | //go:build tools
2 |
3 | package main
4 |
5 | import (
6 | _ "github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile"
7 | )
8 |
--------------------------------------------------------------------------------
/zip_steambuilds.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | name=innovation2007
4 | app_name=Innovation2007.app
5 |
6 | cd bin
7 |
8 | ditto -c -k --keepParent ${app_name} ${name}_darwin_amd64.zip # Use ditto instead of zip to keep metadata
9 | zip ${name}_linux_386.zip ${name}_linux_386
10 | zip ${name}_linux_amd64.zip ${name}_linux_amd64
11 | zip ${name}_windows_386.zip ${name}_windows_386.exe steam_api.dll
12 | zip ${name}_windows_amd64.zip ${name}_windows_amd64.exe steam_api64.dll
13 |
--------------------------------------------------------------------------------