initial commit
@ -0,0 +1,6 @@
|
||||
index.*
|
||||
local/
|
||||
*.o
|
||||
BPmono.ttf
|
||||
pepy
|
||||
compile_commands.json
|
@ -0,0 +1,3 @@
|
||||
[submodule "lib/sb"]
|
||||
path = lib/sb
|
||||
url = makar:/var/www/git/sb
|
@ -0,0 +1,192 @@
|
||||
# Pepy by @ohsqueezy [ohsqueezy.itch.io]
|
||||
|
||||
#######################
|
||||
# Location parameters #
|
||||
#######################
|
||||
|
||||
# Location of project specific source files
|
||||
SRC_DIR := src/
|
||||
|
||||
# Locations of [SPACE BOX] source and dependencies required to be compiled from source. These
|
||||
# locations are configured to match the structure of the [SPACE BOX] repository but can be
|
||||
# modified as necessary.
|
||||
SB_DIR := lib/sb/
|
||||
SB_SRC_DIR := $(SB_DIR)src/
|
||||
SB_LIB_DIR := $(SB_DIR)lib/
|
||||
SDLGFX2_DIR := $(SB_LIB_DIR)sdl2-gfx/
|
||||
GLEW_DIR := $(SB_LIB_DIR)glew/
|
||||
|
||||
# C and C++ compiler commands
|
||||
CC := clang
|
||||
CPPC := clang++
|
||||
|
||||
# Location of SDL config program
|
||||
SDLCONFIG := $(HOME)/local/sdl/bin/sdl2-config
|
||||
|
||||
# Edit to point to the location of BPmono.ttf
|
||||
CREATE_FONT_SYMLINK := ln -nsf $(SB_DIR)"BPmono.ttf" .
|
||||
|
||||
#############################
|
||||
# Based on above parameters #
|
||||
#############################
|
||||
|
||||
SDL_CFLAGS = $(shell $(SDLCONFIG) --cflags)
|
||||
SDL_LFLAGS := $(shell $(SDLCONFIG) --libs)
|
||||
SB_H_FILES := $(wildcard $(addprefix $(SB_SRC_DIR),*.hpp))
|
||||
SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o),$(SB_H_FILES:.hpp=.o))
|
||||
SRC_H_FILES := $(wildcard $(addprefix $(SRC_DIR),*.hpp))
|
||||
SRC_O_FILES := $(SRC_H_FILES:.hpp=.o)
|
||||
|
||||
#####################################################################
|
||||
# Targets for building [SPACE BOX], dependencies and project source #
|
||||
#####################################################################
|
||||
|
||||
$(SDLGFX2_DIR)%.o: $(SDLGFX2_DIR)%.c $(SDLGFX2_DIR)%.h
|
||||
$(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h
|
||||
$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
$(SB_SRC_DIR)extension.o : $(addprefix $(SB_SRC_DIR),Box.hpp Segment.hpp Color.hpp filesystem.hpp Pixels.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Node.o : $(addprefix $(SB_SRC_DIR),Game.hpp Configuration.hpp Delegate.hpp Display.hpp Input.hpp Box.hpp Audio.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Sprite.o : $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Box.hpp Animation.hpp Color.hpp extension.hpp Pixels.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Game.o : $(addprefix $(SB_SRC_DIR),extension.hpp Node.hpp Sprite.hpp Recorder.hpp Input.hpp Configuration.hpp \
|
||||
Delegate.hpp Audio.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Animation.o : $(addprefix $(SB_SRC_DIR),Node.hpp Timer.hpp)
|
||||
$(SB_SRC_DIR)Recorder.o : $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp)
|
||||
$(SB_SRC_DIR)Input.o : $(addprefix $(SB_SRC_DIR),Node.hpp Animation.hpp Configuration.hpp Delegate.hpp)
|
||||
$(SB_SRC_DIR)Configuration.o : $(addprefix $(SB_SRC_DIR),Node.hpp Animation.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Delegate.o : $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Input.hpp)
|
||||
$(SB_SRC_DIR)Display.o : $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)Box.o : $(addprefix $(SB_SRC_DIR),extension.hpp Segment.hpp)
|
||||
$(SB_SRC_DIR)Segment.o : $(addprefix $(SB_SRC_DIR),extension.hpp Box.hpp)
|
||||
$(SB_SRC_DIR)Pixels.o : $(addprefix $(SB_SRC_DIR),Box.hpp extension.hpp Log.hpp utility.hpp)
|
||||
$(SB_SRC_DIR)Audio.o : $(addprefix $(SB_SRC_DIR),Node.hpp Display.hpp Configuration.hpp Box.hpp filesystem.hpp extension.hpp)
|
||||
$(SB_SRC_DIR)GLObject.o : $(addprefix $(SB_SRC_DIR),Log.hpp)
|
||||
$(SB_SRC_DIR)Texture.o : $(addprefix $(SB_SRC_DIR),GLObject.hpp filesystem.hpp Log.hpp)
|
||||
$(SB_SRC_DIR)VBO.o : $(addprefix $(SB_SRC_DIR),Log.hpp GLObject.hpp Attributes.hpp extension.hpp)
|
||||
$(SB_SRC_DIR)Attributes.o : $(addprefix $(SB_SRC_DIR),Log.hpp extension.hpp)
|
||||
$(SRC_DIR)Pepy.o : $(SRC_H_FILES) $(SB_H_FILES)
|
||||
%.o : %.cpp %.hpp
|
||||
$(CPPC) $(CPP_FLAGS) $< -c -o $@
|
||||
|
||||
###############
|
||||
# Linux build #
|
||||
###############
|
||||
|
||||
linux : CC = clang
|
||||
linux : CPPC = clang++
|
||||
linux : CFLAGS = -g -Wall -Wextra -O0 -c -I$(SB_LIB_DIR) -I$(SB_SRC_DIR) $(SDL_CFLAGS)
|
||||
linux : CPP_FLAGS = $(CFLAGS) --std=c++17
|
||||
linux : LFLAGS = $(SDL_LFLAGS) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lstdc++fs
|
||||
linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \
|
||||
$(SB_O_FILES) $(SRC_O_FILES)
|
||||
$(CREATE_FONT_SYMLINK)
|
||||
$(CPPC) $(LFLAGS) -D__LINUX__ $^ -o pepy
|
||||
|
||||
#############
|
||||
# Web build #
|
||||
#############
|
||||
|
||||
# Use Emscripten to output JavaScript and an HTML index page for running in the browser
|
||||
|
||||
EMSCRIPTENHOME = $(HOME)/ext/software/emsdk/upstream/emscripten
|
||||
EMSCRIPTEN_CFLAGS = -O3 -Wall -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="['png']" -s USE_SDL_TTF=2 \
|
||||
-s USE_SDL_MIXER=2 -s SDL2_MIXER_FORMATS="['ogg','mp3']" -s USE_OGG=1 -s USE_VORBIS=1 -s USE_MPG123=1 \
|
||||
-s USE_MODPLUG=1 --no-heap-copy -I$(SB_LIB_DIR) -I$(SB_SRC_DIR)
|
||||
EMSCRIPTEN_LFLAGS = -s MIN_WEBGL_VERSION=2 -s EXPORTED_FUNCTIONS="['_main']" -s ALLOW_MEMORY_GROWTH=1 -s FULL_ES3=1 --shell-file shell.html
|
||||
EMSCRIPTEN_PRELOADS = --preload-file "BPmono.ttf"@/ --preload-file "config.json"@/ --preload-file "resource/"@/"resource/" \
|
||||
--preload-file "src/shader.vert"@/"src/" --preload-file "src/shader.frag"@/"src/"
|
||||
|
||||
emscripten : CC = $(EMSCRIPTENHOME)/emcc
|
||||
emscripten : CPPC = $(EMSCRIPTENHOME)/em++
|
||||
emscripten : CFLAGS = $(EMSCRIPTEN_CFLAGS)
|
||||
emscripten : CPP_FLAGS = $(CFLAGS) --std=c++17
|
||||
emscripten : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES)
|
||||
$(CREATE_FONT_SYMLINK)
|
||||
$(CPPC) $(CPP_FLAGS) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) $^ -o "index.html"
|
||||
|
||||
#########################
|
||||
# Clean up object files #
|
||||
#########################
|
||||
|
||||
clean :
|
||||
-rm $(SRC_DIR)*.o
|
||||
|
||||
clean-all :
|
||||
-find . -iname "*.o" -exec rm {} \;
|
||||
|
||||
#############
|
||||
# compiledb #
|
||||
#############
|
||||
|
||||
# Generate a clang JSON compilation database file. This can be useful for example for code completion. It requires a
|
||||
# compiledb binary (https://pypi.org/project/compiledb/). It should be generated manually every time a file is added,
|
||||
# renamed, or the compilation flags change. The generated database is based on the Linux build.
|
||||
|
||||
PATH_TO_COMPILEDB = $(HOME)/.local/bin/compiledb
|
||||
compiledb :
|
||||
-$(PATH_TO_COMPILEDB) -n make linux -k
|
||||
|
||||
#####################
|
||||
# cross compilation #
|
||||
#####################
|
||||
|
||||
# WARNING: untested
|
||||
|
||||
# Below assignments and targets are necessary for cross-compiling to Android, web (via emscripten), Windows (via mingw),
|
||||
# and OS/X, but cross-compilation targets have not been tested in a while and won't compile without significant changes.
|
||||
|
||||
BUILDDIR := build
|
||||
SDLHOME := $(EXT_SRC_ROOT)/SDL2-2.0.14
|
||||
SDL_IMG_HOME := $(EXT_SRC_ROOT)/SDL2_image-2.0.4
|
||||
SDL_TTF_HOME := $(EXT_SRC_ROOT)/SDL2_ttf-2.0.14
|
||||
GLEW_WIN32_HOME = $(EXT_SRC_ROOT)/glew-2.1.0-win32
|
||||
PROJECTHOME = $(shell pwd)
|
||||
WINBUILDDIR = win
|
||||
SDLMINGWHOME = $(SDLHOME)/i686-w64-mingw32
|
||||
SDL_IMG_MINGW_HOME = $(SDL_IMG_HOME)/i686-w64-mingw32
|
||||
SDL_TTF_MINGW_HOME = $(SDL_TTF_HOME)/i686-w64-mingw32
|
||||
APPDIR = Main.app/Contents
|
||||
SYSFWPATH = /Library/Frameworks
|
||||
|
||||
android :
|
||||
if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi;
|
||||
cd $(SDLHOME)/build-scripts/ && \
|
||||
./androidbuild.sh $(ANDROIDPROJECT) $(PROJECTHOME)/main.cpp
|
||||
cp -r $(SDLHOME)/build/$(ANDROIDPROJECT) $(BUILDDIR)
|
||||
sed -i s/2\.3\.3/2\.2\.3/g $(BUILDDIR)/$(ANDROIDPROJECT)/build.gradle
|
||||
sed -i s/26\.0\.1/23\.0\.1/g $(BUILDDIR)/$(ANDROIDPROJECT)/app/build.gradle
|
||||
cd $(BUILDDIR)/$(ANDROIDPROJECT) && ./gradlew assembleDebug
|
||||
|
||||
mingw :
|
||||
if [ ! -d $(BUILDDIR)/$(WINBUILDDIR) ]; then mkdir -p $(BUILDDIR)/$(WINBUILDDIR); fi;
|
||||
cd $(BUILDDIR)/$(WINBUILDDIR) && \
|
||||
i686-w64-mingw32-g++ -std=c++17 $(PROJECTHOME)/main.cpp -I$(SDLMINGWHOME)/include/SDL2 \
|
||||
-I$(SDL_IMG_MINGW_HOME)/include/SDL2 -I$(SDL_TTF_MINGW_HOME)/include/SDL2 $(INC) \
|
||||
$(PROJECTHOME)/sdl2-gfx/SDL2_gfxPrimitives.c $(PROJECTHOME)/sdl2-gfx/SDL2_rotozoom.c $(PROJECTHOME)/glew/glew.c \
|
||||
-L$(SDLMINGWHOME)/lib -L$(SDL_IMG_MINGW_HOME)/lib -L$(SDL_TTF_MINGW_HOME)/lib \
|
||||
-lmingw32 -lSDL2_image \
|
||||
-lSDL2_ttf -lstdc++fs \
|
||||
-lSDL2main -lSDL2 -lopengl32 -Wall -O2 -o main.exe && \
|
||||
cp $(SDLMINGWHOME)/bin/SDL2.dll $(SDL_IMG_MINGW_HOME)/bin/SDL2_image.dll \
|
||||
$(SDL_TTF_MINGW_HOME)/bin/SDL2_ttf.dll .
|
||||
|
||||
osx :
|
||||
g++ -I $(SYSFWPATH)/SDL2.framework/Headers $(INC) \
|
||||
-I $(SYSFWPATH)/SDL2_image.framework/Headers -Wl,-rpath,$(SYSFWPATH) \
|
||||
-framework SDL2 -framework SDL2_image -framework OpenGL main.cpp sdl2-gfx/SDL2_rotozoom.c \
|
||||
-o main
|
||||
|
||||
osx-bundle :
|
||||
if [ ! -d "$(APPDIR)" ]; then mkdir -p $(APPDIR); fi;
|
||||
if [ ! -d "$(APPDIR)" ]; then mkdir $(APPDIR); fi;
|
||||
if [ ! -d "$(APPDIR)/MacOS" ]; then mkdir $(APPDIR)/MacOS; fi;
|
||||
if [ ! -d "$(APPDIR)/Frameworks" ]; then mkdir $(APPDIR)/Frameworks; fi;
|
||||
if [ ! -d "$(APPDIR)/Resources" ]; then mkdir $(APPDIR)/Resources; fi;
|
||||
touch $(APPDIR)/Info.plist
|
||||
cp -r $(SYSFWPATH)/SDL2.framework $(APPDIR)/Frameworks
|
||||
cp -r $(SYSFWPATH)/SDL2_image.framework $(APPDIR)/Frameworks
|
||||
g++ -I $(SYSFWPATH)/SDL2.framework/Headers -I $(SYSFWPATH)/SDL2_image.framework/Headers \
|
||||
-Wl,-rpath,@executable_path/../Frameworks -Wl,-rpath,$(SYSFWPATH) \
|
||||
-framework SDL2 -framework SDL2_image -framework OpenGL main.cpp -o $(APPDIR)/MacOS/main
|
||||
|
||||
cross : linux android emscripten mingw
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"display":
|
||||
{
|
||||
"dimensions": [960, 540],
|
||||
"framerate": 60,
|
||||
"title": "Pepy",
|
||||
"debug": false,
|
||||
"render driver": "opengles3",
|
||||
"show-cursor": true
|
||||
},
|
||||
"configuration":
|
||||
{
|
||||
"auto-refresh": true
|
||||
},
|
||||
"keys":
|
||||
{
|
||||
},
|
||||
"input":
|
||||
{
|
||||
"any-key-ignore-commands": ["up", "right", "down", "left"],
|
||||
"suppress-any-key-on-mods": true
|
||||
},
|
||||
"log":
|
||||
{
|
||||
"enabled": true,
|
||||
"output-directory": "/var/log/sb/",
|
||||
"debug-to-stdout": false,
|
||||
"debug-to-file": true,
|
||||
"info-file-name": "cuckoo_info.log",
|
||||
"debug-file-name": "cuckoo_debug.log"
|
||||
},
|
||||
"sim":
|
||||
{
|
||||
"wall-count": 48,
|
||||
"ball-scale": 0.15,
|
||||
"spawn-radius": 0.35
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
Subproject commit ee119ecc7e4287838cec5aac127820d4738de17f
|
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 349 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 471 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 284 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 157 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 33 KiB |
@ -0,0 +1,180 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>B.U.D.D.I.</title>
|
||||
<style>
|
||||
@import url("../../lib/fonts/notcouriersans/regular/style.css");
|
||||
body {margin: 0; padding: 0}
|
||||
.emscripten { display: block; }
|
||||
textarea.emscripten { font-family: NotCourierSans; font-size: 24px; width: 960px; resize: none; border: 0px; overflow:hidden }
|
||||
div.emscripten_border { border: 0px solid black; }
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
canvas.emscripten
|
||||
{
|
||||
border: 0px none;
|
||||
background-color: black;
|
||||
width: 960px;
|
||||
height: 540px;
|
||||
}
|
||||
.spinner {
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
-webkit-animation: rotation .8s linear infinite;
|
||||
-moz-animation: rotation .8s linear infinite;
|
||||
-o-animation: rotation .8s linear infinite;
|
||||
animation: rotation 0.8s linear infinite;
|
||||
border-left: 10px solid rgb(0,150,240);
|
||||
border-right: 10px solid rgb(0,150,240);
|
||||
border-bottom: 10px solid rgb(0,150,240);
|
||||
border-top: 10px solid rgb(100,0,200);
|
||||
border-radius: 100%;
|
||||
background-color: rgb(200,100,250);
|
||||
}
|
||||
div#loading
|
||||
{
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 90px;
|
||||
width: 960px;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
}
|
||||
@-webkit-keyframes rotation {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(360deg);}
|
||||
}
|
||||
@-moz-keyframes rotation {
|
||||
from {-moz-transform: rotate(0deg);}
|
||||
to {-moz-transform: rotate(360deg);}
|
||||
}
|
||||
@-o-keyframes rotation {
|
||||
from {-o-transform: rotate(0deg);}
|
||||
to {-o-transform: rotate(360deg);}
|
||||
}
|
||||
@keyframes rotation {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
div#game
|
||||
{
|
||||
position: relative;
|
||||
width: 960px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<image style="width: 140px" src="resource/wad/Mike/0.png">Pepy, it's cuckoo time! Please make it as big as possible using the arrow keys in
|
||||
10 seconds.
|
||||
</div>
|
||||
<div id="game">
|
||||
<div id="loading">
|
||||
<figure style="overflow:visible;" id="spinner"><div class="spinner"></div></figure>
|
||||
<div class="emscripten" id="status">Downloading...</div>
|
||||
<div class="emscripten">
|
||||
<progress value="0" max="100" id="progress" hidden=1></progress>
|
||||
</div>
|
||||
</div>
|
||||
<div class="emscripten_border">
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<textarea class="emscripten" id="output" rows="8" readonly spellcheck="false" wrap="off"></textarea>
|
||||
<img src="resource/Book_of_Pepy/walking_pepy_london.png" /><br />
|
||||
<img src="resource/Book_of_Pepy/1071003012.jpg" /><br />
|
||||
<img src="resource/Book_of_Pepy/129548486_1656033331242674_6748215393958512364_n.jpg" /><br />
|
||||
<img src="resource/Book_of_Pepy/1gfxra.jpg" /><br />
|
||||
<img src="resource/Book_of_Pepy/b89d70e6fb9c4caaed2e797f01bb7575.jpg" /><br />
|
||||
<img src="resource/Book_of_Pepy/cat-party-hat-eats-fish-burger-beige-multi-colored-eating-big-fresh-white-square-plate-drinking-beer-table-183867588.jpg" /><br />
|
||||
<img src="resource/Book_of_Pepy/E6IhBxRXIAETJ29.jpeg" /><br />
|
||||
<img src="resource/Book_of_Pepy/E9GrqOlWYAE2Sgw.jpeg" /><br />
|
||||
<img src="resource/Book_of_Pepy/Ea1zDCEUwAAKUcF.jpeg" /><br />
|
||||
<img src="resource/Book_of_Pepy/EcrFXg5VcAE6tK6.jpeg" /><br />
|
||||
<img src="resource/Book_of_Pepy/Japanese-chocolate-whisky-Morinaga-twig-big-Koeda-whisky-pairing-buy-special-drink-review-photos-4.webp" /><br />
|
||||
<img src="resource/Book_of_Pepy/large.webp" /><br />
|
||||
<img src="resource/Book_of_Pepy/Lenny-Face.png" /><br />
|
||||
<img src="resource/Book_of_Pepy/necropolis_of_Pepy.png" /><br />
|
||||
<img src="resource/Book_of_Pepy/vz-ff8724ba-584e-4f9d-bae5-f7c15e462512.jpeg" /><br />
|
||||
<script type='text/javascript'>
|
||||
var statusElement = document.getElementById('status');
|
||||
var progressElement = document.getElementById('progress');
|
||||
var spinnerElement = document.getElementById('spinner');
|
||||
|
||||
var Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
var element = document.getElementById('output');
|
||||
if (element) element.value = ''; // clear browser cache
|
||||
return function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
// These replacements are necessary if you render to raw HTML
|
||||
//text = text.replace(/&/g, "&");
|
||||
//text = text.replace(/</g, "<");
|
||||
//text = text.replace(/>/g, ">");
|
||||
//text = text.replace('\n', '<br>', 'g');
|
||||
console.log(text);
|
||||
if (element) {
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = element.scrollHeight; // focus on bottom
|
||||
}
|
||||
};
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
||||
// application robust, you may want to override this behavior before shipping!
|
||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||
canvas.addEventListener("webglcontextlost", function(e) {
|
||||
alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||
|
||||
return canvas;
|
||||
})(),
|
||||
setStatus: function(text) {
|
||||
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
|
||||
if (text === Module.setStatus.last.text) return;
|
||||
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
|
||||
var now = Date.now();
|
||||
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
|
||||
Module.setStatus.last.time = now;
|
||||
Module.setStatus.last.text = text;
|
||||
if (m) {
|
||||
text = m[1];
|
||||
progressElement.value = parseInt(m[2])*100;
|
||||
progressElement.max = parseInt(m[4])*100;
|
||||
progressElement.hidden = false;
|
||||
spinnerElement.hidden = false;
|
||||
} else {
|
||||
progressElement.value = null;
|
||||
progressElement.max = null;
|
||||
progressElement.hidden = true;
|
||||
if (!text) spinnerElement.hidden = true;
|
||||
}
|
||||
statusElement.innerHTML = text;
|
||||
},
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
||||
}
|
||||
};
|
||||
Module.setStatus('Downloading...');
|
||||
window.onerror = function() {
|
||||
Module.setStatus('Exception thrown, see JavaScript console');
|
||||
spinnerElement.style.display = 'none';
|
||||
Module.setStatus = function(text) {
|
||||
if (text) Module.printErr('[post-exception status] ' + text);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
{{{ SCRIPT }}}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,160 @@
|
||||
/* Cuckoo by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
#include "Model.hpp"
|
||||
|
||||
/* Default constructor for Model */
|
||||
Model::Model() {};
|
||||
|
||||
/* Construct a Model, adding Attributes each already wrapped in a shared pointer. The attributes should
|
||||
* be passed as a map with each key being a name and each value being a shared pointer to attributes. */
|
||||
Model::Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes_pack)
|
||||
{
|
||||
for (auto attributes : attributes_pack)
|
||||
{
|
||||
this->attributes(attributes.second, attributes.first);
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct a Model, adding Attributes, which will each be wrapped in a shared pointer and stored in the
|
||||
* created object. The attributes should be passed as a map with each key being a name and each value being
|
||||
* an attributes object. */
|
||||
Model::Model(const std::map<std::string, sb::Attributes>& attributes_pack)
|
||||
{
|
||||
for (auto attributes : attributes_pack)
|
||||
{
|
||||
this->attributes(attributes.second, attributes.first);
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct a new model object by passing a list of names which will be used to initialize
|
||||
* empty attributes objects with the given names */
|
||||
Model::Model(const std::initializer_list<std::string>& names)
|
||||
{
|
||||
for (const std::string& name : names)
|
||||
{
|
||||
this->attributes(sb::Attributes(), name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the entire map of attributes, each wrapped in its shared pointer held by this object.
|
||||
* Can be used to iterate through the attributes. */
|
||||
std::map<std::string, std::shared_ptr<sb::Attributes>>& Model::attributes()
|
||||
{
|
||||
return model_attributes;
|
||||
}
|
||||
|
||||
/* Get the attributes under name, wrapped in the shared pointer held by this object. This
|
||||
* function uses the at method of std::map, so name must refer to attributes already
|
||||
* stored in this model. Use this function to share ownership of the attributes or to gain
|
||||
* access to the public interface of the attributes. */
|
||||
std::shared_ptr<sb::Attributes>& Model::attributes(const std::string& name)
|
||||
{
|
||||
return attributes().at(name);
|
||||
}
|
||||
|
||||
/* Get the attributes under name, wrapped in the shared pointer held by this object. This
|
||||
* function uses operator[] or std::map, so this can be used to add new attributes to the
|
||||
* object if they are wrapped in a shared pointer. */
|
||||
std::shared_ptr<sb::Attributes>& Model::operator[](const std::string& name)
|
||||
{
|
||||
auto element = attributes().find(name);
|
||||
/* add an empty Attributes at name if it doesn't exist yet */
|
||||
if (element == attributes().end())
|
||||
{
|
||||
attributes(sb::Attributes{}, name);
|
||||
}
|
||||
return attributes()[name];
|
||||
}
|
||||
|
||||
/* Assign name to attributes, copy and wrap in a shared pointer. The model can share
|
||||
* ownership of the created attribute memory with callers that request it. */
|
||||
void Model::attributes(const sb::Attributes& attributes, const std::string& name)
|
||||
{
|
||||
this->attributes(std::make_shared<sb::Attributes>(attributes), name);
|
||||
}
|
||||
|
||||
/* Assign name to attributes and share ownership. */
|
||||
void Model::attributes(const std::shared_ptr<sb::Attributes>& attributes, const std::string& name)
|
||||
{
|
||||
this->attributes()[name] = attributes;
|
||||
}
|
||||
|
||||
/* Enable all attributes. */
|
||||
void Model::enable()
|
||||
{
|
||||
for (const auto& attributes : this->attributes())
|
||||
{
|
||||
attributes.second->enable();
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable all attributes. */
|
||||
void Model::disable()
|
||||
{
|
||||
for (const auto& attributes : this->attributes())
|
||||
{
|
||||
attributes.second->disable();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a reference to the texture container. */
|
||||
std::map<std::string, sb::Texture>& Model::textures()
|
||||
{
|
||||
return model_textures;
|
||||
}
|
||||
|
||||
/* Get the texture at name. This can be used to read the texture memory, share ownership of it, or
|
||||
* anything else a Texture object can be used for with direct calls to GL functions. */
|
||||
sb::Texture& Model::texture(const std::string& name)
|
||||
{
|
||||
return textures().at(name);
|
||||
}
|
||||
|
||||
/* Get the default texture. The default texture must have previously been set with the default key as
|
||||
* the name, which can be done using Model::texture(sb::Texture). */
|
||||
sb::Texture& Model::texture()
|
||||
{
|
||||
return texture(DEFAULT_TEXTURE_NAME);
|
||||
}
|
||||
|
||||
/* Assign name to texture and share ownership. */
|
||||
void Model::texture(const sb::Texture& texture, const std::string& name)
|
||||
{
|
||||
textures()[name] = texture;
|
||||
}
|
||||
|
||||
/* If no name is specified, use the default texture. This can be used to conveniently setup a model
|
||||
* with only one texture. */
|
||||
void Model::texture(const sb::Texture& texture)
|
||||
{
|
||||
this->texture(texture, DEFAULT_TEXTURE_NAME);
|
||||
}
|
||||
|
||||
/* Get the model's transformation matrix. */
|
||||
const glm::mat4& Model::transformation() const
|
||||
{
|
||||
return model_transformation;
|
||||
}
|
||||
|
||||
/* Set the model's transformation matrix. */
|
||||
void Model::transformation(const glm::mat4& transformation)
|
||||
{
|
||||
model_transformation = transformation;
|
||||
}
|
||||
|
||||
/* Return the size in bytes of the sum of the attributes. */
|
||||
std::size_t Model::size()
|
||||
{
|
||||
std::size_t sum = 0;
|
||||
for (const auto& attributes : this->attributes())
|
||||
{
|
||||
sum += attributes.second->size();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Return the transformation matrix. */
|
||||
Model::operator glm::mat4() const
|
||||
{
|
||||
return model_transformation;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/* Cuckoo by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
#ifndef MODEL_H_
|
||||
#define MODEL_H_
|
||||
|
||||
/* GL functions */
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include "glew/glew.h"
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
#include "glm/glm.hpp"
|
||||
#include "Attributes.hpp"
|
||||
#include "Texture.hpp"
|
||||
|
||||
class Model
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
inline static const std::string DEFAULT_TEXTURE_NAME = "default";
|
||||
std::map<std::string, sb::Texture> model_textures;
|
||||
std::map<std::string, std::shared_ptr<sb::Attributes>> model_attributes;
|
||||
glm::mat4 model_transformation {1.0f};
|
||||
|
||||
public:
|
||||
|
||||
Model();
|
||||
Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>&);
|
||||
Model(const std::map<std::string, sb::Attributes>&);
|
||||
Model(const std::initializer_list<std::string>&);
|
||||
std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes();
|
||||
std::shared_ptr<sb::Attributes>& attributes(const std::string&);
|
||||
void attributes(const sb::Attributes&, const std::string&);
|
||||
void attributes(const std::shared_ptr<sb::Attributes>&, const std::string&);
|
||||
std::shared_ptr<sb::Attributes>& operator[](const std::string&);
|
||||
void enable();
|
||||
void disable();
|
||||
std::map<std::string, sb::Texture>& textures();
|
||||
sb::Texture& texture(const std::string&);
|
||||
sb::Texture& texture();
|
||||
void texture(const sb::Texture&, const std::string&);
|
||||
void texture(const sb::Texture&);
|
||||
const glm::mat4& transformation() const;
|
||||
void transformation(const glm::mat4&);
|
||||
std::size_t size();
|
||||
operator glm::mat4() const;
|
||||
|
||||
};
|
||||
|
||||
class Plane : public Model
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
inline const static std::shared_ptr<sb::Attributes> position = std::make_shared<sb::Attributes>(sb::Attributes{
|
||||
{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f},
|
||||
{1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f}
|
||||
});
|
||||
inline const static std::shared_ptr<sb::Attributes> uv = std::make_shared<sb::Attributes>(sb::Attributes{
|
||||
{0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
|
||||
{1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}
|
||||
});
|
||||
|
||||
Plane() : Model(std::map<std::string, std::shared_ptr<sb::Attributes>>({{"position", position}, {"uv", uv}})) {}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,383 @@
|
||||
/* Pepy by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
#include "Pepy.hpp"
|
||||
|
||||
/* Launch the Pepy instance's mainloop */
|
||||
int main()
|
||||
{
|
||||
Pepy pepy = Pepy();
|
||||
pepy.run();
|
||||
pepy.quit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize a Pepy instance */
|
||||
Pepy::Pepy()
|
||||
{
|
||||
/* subscribe to command events */
|
||||
get_delegate().subscribe(&Pepy::respond, this);
|
||||
get_delegate().subscribe(&Pepy::respond, this, SDL_MOUSEBUTTONDOWN);
|
||||
get_delegate().subscribe(&Pepy::respond, this, SDL_MOUSEBUTTONUP);
|
||||
/* create a glowing ring */
|
||||
int point_count = configuration()["sim"]["wall-count"].get<int>() + 1;
|
||||
std::vector<glm::vec2> outer_points = sb::points_on_circle(point_count, 0.75f, {0.0f, 0.0f});
|
||||
std::vector<glm::vec2> inner_points = sb::points_on_circle(point_count, 0.65f, {0.0f, 0.0f});
|
||||
float inner_saturation = 0.1f;
|
||||
float inner_value = 1.0f;
|
||||
float outer_saturation = 1.0f;
|
||||
float outer_value = 0.1f;
|
||||
int next;
|
||||
for (int ii = 0; ii <= point_count; ii++)
|
||||
{
|
||||
next = (ii + 1) % point_count;
|
||||
cuckoo["position"]->add(outer_points[ii]);
|
||||
cuckoo["position"]->add(outer_points[next]);
|
||||
cuckoo["position"]->add(inner_points[ii]);
|
||||
cuckoo["position"]->add(inner_points[ii]);
|
||||
cuckoo["position"]->add(inner_points[next]);
|
||||
cuckoo["position"]->add(outer_points[next]);
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(ii / static_cast<float>(point_count) * 255.0f, outer_saturation, outer_value)));
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(next / static_cast<float>(point_count) * 255.0f, outer_saturation, outer_value)));
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(ii / static_cast<float>(point_count) * 255.0f, inner_saturation, inner_value)));
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(ii / static_cast<float>(point_count) * 255.0f, inner_saturation, inner_value)));
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(next / static_cast<float>(point_count) * 255.0f, inner_saturation, inner_value)));
|
||||
cuckoo["color"]->add(glm::rgbColor(glm::vec3(next / static_cast<float>(point_count) * 255.0f, outer_saturation, outer_value)));
|
||||
}
|
||||
/* create balls */
|
||||
float size = configuration()["sim"]["ball-scale"];
|
||||
auto spawn_points = sb::points_on_circle(5, configuration()["sim"]["spawn-radius"]);
|
||||
for (auto spawn_point : spawn_points)
|
||||
{
|
||||
Plane ball;
|
||||
ball.transformation(glm::translate(glm::vec3{spawn_point.x, spawn_point.y, 1.0f}) * glm::scale(glm::vec3{size, size, 1.0f}));
|
||||
wad.push_back(std::pair{ball, glm::vec2{0.0f, 0.0f}});
|
||||
}
|
||||
background.transformation(glm::scale(glm::vec3{5.0f, 5.0f, 1.0f}));
|
||||
/* load Open GL */
|
||||
load_gl_context();
|
||||
/* load wad textures */
|
||||
sb::Texture wad_texture {"resource/wad.png"};
|
||||
wad_texture.load();
|
||||
/* Apply the wad texture to each wad */
|
||||
for (size_t wad_ii = 0; wad_ii < wad.size(); wad_ii++)
|
||||
{
|
||||
wad[wad_ii].first.texture(wad_texture);
|
||||
}
|
||||
sb::Texture texture {"resource/space.png"};
|
||||
texture.load();
|
||||
background.texture(texture);
|
||||
}
|
||||
|
||||
/* Create GL context via super class and load vertices, UV data, and shaders */
|
||||
void Pepy::load_gl_context()
|
||||
{
|
||||
super::load_gl_context();
|
||||
cuckoo_vao.generate();
|
||||
wad_vao.generate();
|
||||
cuckoo_vao.bind();
|
||||
/* Generate ID for the vertex buffer object that will hold vertex data. Because there is one buffer, data
|
||||
* will be copied in one after the other, offset to after the previous location. */
|
||||
vbo.generate();
|
||||
vbo.bind();
|
||||
vbo.allocate(cuckoo.size() + wad[0].first.size(), GL_STATIC_DRAW);
|
||||
GLuint vertex_shader = load_shader("src/shader.vert", GL_VERTEX_SHADER);
|
||||
GLuint fragment_shader = load_shader("src/shader.frag", GL_FRAGMENT_SHADER);
|
||||
shader = glCreateProgram();
|
||||
glAttachShader(shader, vertex_shader);
|
||||
glAttachShader(shader, fragment_shader);
|
||||
sb::Log::gl_errors("after attaching shaders");
|
||||
cuckoo.attributes("position")->bind(0, shader, "vertex_position");
|
||||
cuckoo.attributes("color")->bind(1, shader, "vertex_color");
|
||||
vbo.add(*cuckoo.attributes("position"));
|
||||
vbo.add(*cuckoo.attributes("color"));
|
||||
wad_vao.bind();
|
||||
wad[0].first.attributes("position")->bind(0, shader, "vertex_position");
|
||||
wad[0].first.attributes("uv")->bind(2, shader, "vertex_uv");
|
||||
vbo.add(*wad[0].first.attributes("position"));
|
||||
vbo.add(*wad[0].first.attributes("uv"));
|
||||
sb::Log::gl_errors("after VBO allocation");
|
||||
link_shader(shader);
|
||||
uniform["blend"] = glGetUniformLocation(shader, "blend_min_hsv");
|
||||
uniform["orthographic_projection"] = glGetUniformLocation(shader, "orthographic_projection");
|
||||
uniform["model_transformation"] = glGetUniformLocation(shader, "model_transformation");
|
||||
uniform["base_texture"] = glGetUniformLocation(shader, "base_texture");
|
||||
uniform["textured"] = glGetUniformLocation(shader, "textured");
|
||||
uniform["scroll"] = glGetUniformLocation(shader, "scroll");
|
||||
uniform["time"] = glGetUniformLocation(shader, "time");
|
||||
sb::Log::gl_errors("after uniforms");
|
||||
/* enable alpha rendering */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
sb::Log::gl_errors("at end of load context");
|
||||
}
|
||||
|
||||
void Pepy::respond(SDL_Event& event)
|
||||
{
|
||||
/* Will check if reset should be triggered */
|
||||
bool reset = false;
|
||||
/* Check for any direction when waiting to reset */
|
||||
if (stopped && delegate.compare(event, {"up", "down", "left", "right"}))
|
||||
{
|
||||
reset = true;
|
||||
}
|
||||
if (event.type == SDL_MOUSEBUTTONDOWN)
|
||||
{
|
||||
if (shaking)
|
||||
{
|
||||
grabbed = true;
|
||||
}
|
||||
/* Mouse button will trigger reset when stopped */
|
||||
else if (stopped)
|
||||
{
|
||||
reset = true;
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_MOUSEBUTTONUP && shaking)
|
||||
{
|
||||
grabbed = false;
|
||||
}
|
||||
/* Reset to countdown */
|
||||
if (reset)
|
||||
{
|
||||
float size = configuration()["sim"]["ball-scale"];
|
||||
auto spawn_points = sb::points_on_circle(5, configuration()["sim"]["spawn-radius"]);
|
||||
int ii = 0;
|
||||
for (auto& ball : wad)
|
||||
{
|
||||
ball.first.transformation(glm::translate(glm::vec3{spawn_points[ii].x, spawn_points[ii++].y, 1.0f}) * glm::scale(glm::vec3{size, size, 1.0f}));
|
||||
}
|
||||
stopped = false;
|
||||
shaking = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update state and draw the screen */
|
||||
void Pepy::update()
|
||||
{
|
||||
/* number of seconds running */
|
||||
time_seconds = SDL_GetTicks() / 1000.0f;
|
||||
if (shaking)
|
||||
{
|
||||
countdown -= last_frame_length / 1000.0f;
|
||||
if (countdown < 0.0f)
|
||||
{
|
||||
shaking = false;
|
||||
flying = true;
|
||||
countdown = 10.0f;
|
||||
}
|
||||
}
|
||||
/* move cuckoo with mouse */
|
||||
if (grabbed && shaking)
|
||||
{
|
||||
/* get mouse coordinates in NDC */
|
||||
SDL_GetMouseState(&mouse_pixel.x, &mouse_pixel.y);
|
||||
glm::vec2 mouse_ndc {
|
||||
static_cast<float>(mouse_pixel.x) / window_box().width() * 2.0f - 1.0f,
|
||||
(1.0f - static_cast<float>(mouse_pixel.y) / window_box().height()) * 2.0f - 1.0f
|
||||
};
|
||||
cuckoo_offset.x += weight(mouse_ndc.x / 20.0f) * std::max(std::min(std::abs(1.0f - cuckoo_offset.x), 1.0f), 0.1f);
|
||||
cuckoo_offset.y += weight(mouse_ndc.y / 20.0f) * std::max(std::min(std::abs(1.0f - cuckoo_offset.y), 1.0f), 0.1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move cuckoo with keys */
|
||||
const std::uint8_t* state = SDL_GetKeyboardState(nullptr);
|
||||
float motion = weight(1 / 25.0f), diagonal = motion * std::sin(glm::pi<float>() * 0.25f);
|
||||
if (state[SDL_SCANCODE_UP])
|
||||
{
|
||||
if (state[SDL_SCANCODE_RIGHT])
|
||||
{
|
||||
cuckoo_offset.x += diagonal;
|
||||
cuckoo_offset.y += diagonal;
|
||||
}
|
||||
else if (state[SDL_SCANCODE_LEFT])
|
||||
{
|
||||
cuckoo_offset.x -= diagonal;
|
||||
cuckoo_offset.y += diagonal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cuckoo_offset.y += motion;
|
||||
}
|
||||
}
|
||||
else if (state[SDL_SCANCODE_RIGHT])
|
||||
{
|
||||
if (state[SDL_SCANCODE_DOWN])
|
||||
{
|
||||
cuckoo_offset.x += diagonal;
|
||||
cuckoo_offset.y -= diagonal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cuckoo_offset.x += motion;
|
||||
}
|
||||
}
|
||||
else if (state[SDL_SCANCODE_DOWN])
|
||||
{
|
||||
if (state[SDL_SCANCODE_LEFT])
|
||||
{
|
||||
cuckoo_offset.x -= diagonal;
|
||||
cuckoo_offset.y -= diagonal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cuckoo_offset.y -= motion;
|
||||
}
|
||||
}
|
||||
else if (state[SDL_SCANCODE_LEFT])
|
||||
{
|
||||
cuckoo_offset.x -= motion;
|
||||
}
|
||||
}
|
||||
cuckoo_offset.x -= weight(glm::sign(cuckoo_offset).x * return_speed);
|
||||
cuckoo_offset.y -= weight(glm::sign(cuckoo_offset).y * return_speed);
|
||||
cuckoo.transformation(glm::translate(cuckoo_offset));
|
||||
hue_offset += weight(0.002f);
|
||||
glm::vec2 x_range = {-1.0f, 1.0f};
|
||||
glm::vec2 y_range = {-1.0f, 1.0f};
|
||||
/* move wad */
|
||||
bool all_stopped = true;
|
||||
for (auto& ball : wad)
|
||||
{
|
||||
const glm::vec2& ball_center = {ball.first.transformation()[3].x, ball.first.transformation()[3].y};
|
||||
const glm::vec2& cuckoo_center = {cuckoo.transformation()[3].x, cuckoo.transformation()[3].y};
|
||||
float distance = glm::distance(ball_center, cuckoo_center);
|
||||
if (shaking)
|
||||
{
|
||||
if (distance > 0.65f)
|
||||
{
|
||||
float angle = glm::atan(cuckoo_center.y - ball_center.y, cuckoo_center.x - ball_center.x);
|
||||
ball.second.y += 0.0005f;
|
||||
ball.second.x = angle + glm::half_pi<float>();
|
||||
}
|
||||
}
|
||||
glm::vec2 step {glm::sin(ball.second.x) * ball.second.y, -glm::cos(ball.second.x) * ball.second.y};
|
||||
ball.first.transformation(glm::translate(glm::vec3{step.x, step.y, 0.0f}) * ball.first.transformation());
|
||||
if (ball.second.y > 0)
|
||||
{
|
||||
float friction;
|
||||
if (shaking)
|
||||
{
|
||||
friction = 0.00005f;
|
||||
}
|
||||
else
|
||||
{
|
||||
friction = 0.0001f;
|
||||
}
|
||||
ball.second.y = std::max(0.0f, ball.second.y - friction);
|
||||
}
|
||||
if (ball_center.x < x_range[0])
|
||||
{
|
||||
x_range[0] = ball_center.x - 0.1f;
|
||||
}
|
||||
else if (ball_center.x > x_range[1])
|
||||
{
|
||||
x_range[1] = ball_center.x + 0.1f;
|
||||
}
|
||||
if (ball_center.y < y_range[0])
|
||||
{
|
||||
y_range[0] = ball_center.y - 0.1f;
|
||||
}
|
||||
else if (ball_center.y > y_range[1])
|
||||
{
|
||||
y_range[1] = ball_center.y + 0.1f;
|
||||
}
|
||||
if (ball.second.y > 0.0f)
|
||||
{
|
||||
all_stopped = false;
|
||||
}
|
||||
}
|
||||
if (all_stopped && flying)
|
||||
{
|
||||
flying = false;
|
||||
stopped = true;
|
||||
glm::vec2 sum {0.0f, 0.0f};
|
||||
std::vector<glm::vec2> centers;
|
||||
for (auto& ball : wad)
|
||||
{
|
||||
const glm::vec2& ball_center = {ball.first.transformation()[3].x, ball.first.transformation()[3].y};
|
||||
centers.push_back(ball_center);
|
||||
sum += ball_center;
|
||||
}
|
||||
glm::vec2 centroid = sum / wad.size();
|
||||
angle_sort sorter {centroid, centers[0]};
|
||||
std::sort(centers.begin(), centers.end(), sorter);
|
||||
float area = 0.0f;
|
||||
for (std::size_t center_ii = 0; center_ii < centers.size() - 1; center_ii++)
|
||||
{
|
||||
area += centers[center_ii].x * centers[center_ii + 1].y - centers[center_ii + 1].x * centers[center_ii].y;
|
||||
}
|
||||
area += centers[centers.size() - 1].x * centers[0].y - centers[0].x * centers[centers.size() - 1].y;
|
||||
area = std::abs(area) / 2.0f;
|
||||
std::cout << "Your score (size) is " << area << ". Press arrow key to play again." << std::endl;
|
||||
}
|
||||
/* paint over screen */
|
||||
glClearColor(0, 0, 0, 1);
|
||||
sb::Log::gl_errors("after setting clear color");
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
sb::Log::gl_errors("after clearing screen");
|
||||
glUseProgram(shader);
|
||||
sb::Log::gl_errors("after using program");
|
||||
/* set orthographic project for viewing entire scene at normalized screen ratio */
|
||||
aspect_ratio = window_box().aspect(true);
|
||||
if (window_box().width() > window_box().height())
|
||||
{
|
||||
orthographic_projection = glm::ortho(aspect_ratio * x_range[0], aspect_ratio * x_range[1], y_range[0], y_range[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
orthographic_projection = glm::ortho(x_range[0], x_range[1], aspect_ratio * y_range[0], aspect_ratio * y_range[1]);
|
||||
}
|
||||
glUniformMatrix4fv(uniform["orthographic_projection"], 1, GL_FALSE, &orthographic_projection[0][0]);
|
||||
sb::Log::gl_errors("after setting orthographic projection");
|
||||
/* draw background */
|
||||
wad_vao.bind();
|
||||
glUniform3f(uniform["blend"], hue_offset, 0.0f, 1.0f);
|
||||
glUniform1i(uniform["textured"], true);
|
||||
glUniform1i(uniform["scroll"], true);
|
||||
glUniform1f(uniform["time"], time_seconds);
|
||||
glUniform1i(uniform["base_texture"], 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
background.texture().bind();
|
||||
glUniformMatrix4fv(uniform["model_transformation"], 1, GL_FALSE, reinterpret_cast<const GLfloat*>(&background.transformation()[0][0]));
|
||||
background.enable();
|
||||
glDrawArrays(GL_TRIANGLES, 0, background.attributes("position")->count());
|
||||
background.disable();
|
||||
/* draw wad */
|
||||
wad_vao.bind();
|
||||
glUniform3f(uniform["blend"], 0.0f, 0.0f, 1.0f);
|
||||
glUniform1i(uniform["textured"], true);
|
||||
glUniform1i(uniform["scroll"], false);
|
||||
sb::Log::gl_errors("after setting blending and textured flag");
|
||||
for (std::pair<Plane, glm::vec2>& ball : wad)
|
||||
{
|
||||
glUniform1i(uniform["base_texture"], 0);
|
||||
sb::Log::gl_errors("after setting texture uniform");
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
sb::Log::gl_errors("after activating texture");
|
||||
ball.first.texture().bind();
|
||||
sb::Log::gl_errors("after binding wad");
|
||||
glUniformMatrix4fv(uniform["model_transformation"], 1, GL_FALSE, reinterpret_cast<const GLfloat*>(&ball.first.transformation()[0][0]));
|
||||
ball.first.enable();
|
||||
glDrawArrays(GL_TRIANGLES, 0, ball.first.attributes("position")->count());
|
||||
ball.first.disable();
|
||||
sb::Log::gl_errors("after drawing wad");
|
||||
}
|
||||
/* draw cuckoo */
|
||||
if (shaking || stopped)
|
||||
{
|
||||
cuckoo_vao.bind();
|
||||
glUniform3f(uniform["blend"], hue_offset, 0.5f, 1.0f);
|
||||
glUniform1i(uniform["textured"], false);
|
||||
glUniformMatrix4fv(uniform["model_transformation"], 1, GL_FALSE, reinterpret_cast<const GLfloat*>(&cuckoo.transformation()[0][0]));
|
||||
cuckoo.enable();
|
||||
glDrawArrays(GL_TRIANGLES, 0, cuckoo.attributes("position")->count());
|
||||
cuckoo.disable();
|
||||
}
|
||||
SDL_GL_SwapWindow(window());
|
||||
sb::Log::gl_errors("at end of update");
|
||||
if (shaking)
|
||||
{
|
||||
std::cout << countdown << std::endl;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/* Pepy by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
#ifndef PEPY_H_
|
||||
#define PEPY_H_
|
||||
|
||||
/* Enable swizzling in GLM */
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/compatibility.hpp>
|
||||
|
||||
/* [SPACE BOX] headers */
|
||||
#include "Game.hpp"
|
||||
#include "VBO.hpp"
|
||||
|
||||
/* Project headers */
|
||||
#include "Model.hpp"
|
||||
|
||||
class angle_sort
|
||||
{
|
||||
glm::vec2 m_origin;
|
||||
glm::vec2 m_dreference;
|
||||
|
||||
// z-coordinate of cross-product, aka determinant
|
||||
static double xp(glm::vec2 a, glm::vec2 b) { return a.x * b.y - a.y * b.x; }
|
||||
|
||||
public:
|
||||
|
||||
angle_sort(const glm::vec2 origin, const glm::vec2 reference) : m_origin(origin), m_dreference(reference - origin) {}
|
||||
|
||||
bool operator()(const glm::vec2 a, const glm::vec2 b) const
|
||||
{
|
||||
const glm::vec2 da = a - m_origin, db = b - m_origin;
|
||||
const double detb = xp(m_dreference, db);
|
||||
|
||||
// nothing is less than zero degrees
|
||||
if (detb == 0 && db.x * m_dreference.x + db.y * m_dreference.y >= 0) return false;
|
||||
|
||||
const double deta = xp(m_dreference, da);
|
||||
|
||||
// zero degrees is less than anything else
|
||||
if (deta == 0 && da.x * m_dreference.x + da.y * m_dreference.y >= 0) return true;
|
||||
|
||||
if (deta * detb >= 0) {
|
||||
// both on same side of reference, compare to each other
|
||||
return xp(da, db) > 0;
|
||||
}
|
||||
|
||||
// vectors "less than" zero degrees are actually large, near 2 pi
|
||||
return deta > 0;
|
||||
}
|
||||
};
|
||||
|
||||
class Pepy : public Game
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
/* Convention for calling parent class in a consistent way across classes */
|
||||
typedef Game super;
|
||||
|
||||
bool shaking = true, flying = false, stopped = false;
|
||||
sb::VAO cuckoo_vao, wad_vao;
|
||||
sb::VBO vbo;
|
||||
GLuint shader;
|
||||
Model cuckoo;
|
||||
std::vector<std::pair<Plane, glm::vec2>> wad;
|
||||
std::map<std::string, GLuint> uniform;
|
||||
float hue_offset = 0.0f, time_seconds = 0.0f, aspect_ratio = 1.0f, return_speed = 0.0075f, cuckoo_speed = 0.0f, countdown = 10.0f;
|
||||
glm::mat4 orthographic_projection {1};
|
||||
glm::vec3 cuckoo_offset {0.0f, 0.0f, 0.0f};
|
||||
bool grabbed = false;
|
||||
glm::ivec2 mouse_pixel = {0, 0};
|
||||
Plane background;
|
||||
|
||||
void load_gl_context();
|
||||
void update();
|
||||
|
||||
public:
|
||||
|
||||
Pepy();
|
||||
void respond(SDL_Event&);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,44 @@
|
||||
#version 300 es
|
||||
|
||||
/* Pepy by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
precision mediump float;
|
||||
in vec2 uv;
|
||||
in vec3 color;
|
||||
uniform sampler2D base_texture;
|
||||
uniform vec3 blend_min_hsv;
|
||||
uniform float time;
|
||||
uniform bool scroll;
|
||||
uniform bool textured;
|
||||
out vec4 myOutputColor;
|
||||
|
||||
/* from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl, licensed under WTFPL */
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if (textured)
|
||||
{
|
||||
// if (scroll)
|
||||
// {
|
||||
// ivec2 texture_size = textureSize(base_texture, 0);
|
||||
// float speed = time * 35.0;
|
||||
// gl_FragColor = texelFetch(base_texture, ivec2(mod(vec2(gl_FragCoord.x + speed, gl_FragCoord.y - speed), texture_size)), 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
myOutputColor = texture(base_texture, uv);
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
myOutputColor = vec4(color, 1.0);
|
||||
}
|
||||
/* apply blending, leaving alpha unchanged */
|
||||
myOutputColor.xyz = min(myOutputColor.xyz, hsv2rgb(blend_min_hsv));
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#version 300 es
|
||||
|
||||
/* Pepy by @ohsqueezy [ohsqueezy.itch.io] */
|
||||
|
||||
precision mediump float;
|
||||
in vec2 vertex_position;
|
||||
in vec2 vertex_uv;
|
||||
in vec3 vertex_color;
|
||||
out vec2 uv;
|
||||
out vec3 color;
|
||||
uniform mat4 model_transformation;
|
||||
uniform mat4 orthographic_projection;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = orthographic_projection * model_transformation * vec4(vertex_position, 0, 1);
|
||||
uv = vertex_uv;
|
||||
color = vertex_color;
|
||||
}
|