diff --git a/CarCrimeCity/Part2/Lua533/include/lauxlib.h b/CarCrimeCity/Part2/Lua533/include/lauxlib.h new file mode 100644 index 0000000..ddb7c22 --- /dev/null +++ b/CarCrimeCity/Part2/Lua533/include/lauxlib.h @@ -0,0 +1,256 @@ +/* +** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + + +/* extra error code for 'luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/CarCrimeCity/Part2/Lua533/include/lua.h b/CarCrimeCity/Part2/Lua533/include/lua.h new file mode 100644 index 0000000..f78899f --- /dev/null +++ b/CarCrimeCity/Part2/Lua533/include/lua.h @@ -0,0 +1,486 @@ +/* +** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "3" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2016 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2016 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/CarCrimeCity/Part2/Lua533/include/lua.hpp b/CarCrimeCity/Part2/Lua533/include/lua.hpp new file mode 100644 index 0000000..ec417f5 --- /dev/null +++ b/CarCrimeCity/Part2/Lua533/include/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/CarCrimeCity/Part2/Lua533/include/luaconf.h b/CarCrimeCity/Part2/Lua533/include/luaconf.h new file mode 100644 index 0000000..867e9cb --- /dev/null +++ b/CarCrimeCity/Part2/Lua533/include/luaconf.h @@ -0,0 +1,769 @@ +/* +** $Id: luaconf.h,v 1.255 2016/05/01 20:06:09 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS +#endif + + + +/* +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. +*/ +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 +#endif + + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options (if supported +** by your C compiler). The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif + +/* }================================================================== */ + + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll;" \ + LUA_CDIR"?53.dll;" ".\\?53.dll" + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so;" \ + LUA_CDIR"lib?53.so;" "./lib?53.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +** that are not to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_2) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. +*/ +#define LUA_COMPAT_BITLIB + +/* +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +*/ +#define LUA_COMPAT_APIINTCASTS + +#endif /* } */ + + +#if defined(LUA_COMPAT_5_1) /* { */ + +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeric string to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n)) + +/* +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_mathlim(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_mathlim(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_mathlim(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of an 'usual argument conversion' +@@ over a lUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" +#define lua_integer2str(s,sz,n) l_sprintf((s), sz, LUA_INTEGER_FMT, (n)) + +#define LUAI_UACINT LUA_INTEGER + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) ((void)L, l_sprintf(b,sz,f,n)) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). You probably do not want/need to change them. +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) +*/ +#if defined(LUA_FLOAT_LONGDOUBLE) +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif + +/* }================================================================== */ + + +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/CarCrimeCity/Part2/Lua533/include/lualib.h b/CarCrimeCity/Part2/Lua533/include/lualib.h new file mode 100644 index 0000000..5165c0f --- /dev/null +++ b/CarCrimeCity/Part2/Lua533/include/lualib.h @@ -0,0 +1,58 @@ +/* +** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/CarCrimeCity/Part2/Lua533/liblua53.a b/CarCrimeCity/Part2/Lua533/liblua53.a new file mode 100644 index 0000000..32646db Binary files /dev/null and b/CarCrimeCity/Part2/Lua533/liblua53.a differ diff --git a/CarCrimeCity/Part2/Lua533/lua53.dll b/CarCrimeCity/Part2/Lua533/lua53.dll new file mode 100644 index 0000000..2ab8168 Binary files /dev/null and b/CarCrimeCity/Part2/Lua533/lua53.dll differ diff --git a/CarCrimeCity/Part2/assets/buildings/udxs_building1.obj b/CarCrimeCity/Part2/assets/buildings/udxs_building1.obj new file mode 100644 index 0000000..fe83e45 --- /dev/null +++ b/CarCrimeCity/Part2/assets/buildings/udxs_building1.obj @@ -0,0 +1,716 @@ +# Blender v2.79 (sub 0) OBJ File: 'olc_building0.blend' +# www.blender.org +mtllib olc_building0.mtl +o Plane +v 0.000000 0.000000 0.000000 +v 0.000000 -1.000000 0.000000 +v -1.000000 0.000000 0.000000 +v -1.000000 -1.000000 0.000000 +v -0.025000 -0.412671 -0.052133 +v -0.025000 -0.587329 -0.052133 +v -0.975000 -0.025000 -0.050000 +v -0.975000 -0.975000 -0.050000 +v -1.000000 0.000000 -0.050000 +v 0.000000 0.000000 -0.050000 +v 0.000000 -1.000000 -0.050000 +v -1.000000 -1.000000 -0.050000 +v -0.975000 -0.025000 -0.517611 +v -0.975000 -0.975000 -0.517611 +v -1.000000 0.000000 -0.527316 +v 0.000000 0.000000 -0.527316 +v 0.000000 -1.000000 -0.527316 +v -1.000000 -1.000000 -0.527316 +v -0.975000 -0.025000 -0.550000 +v -0.025000 -0.025000 -0.550000 +v -0.025000 -0.975000 -0.550000 +v -0.975000 -0.975000 -0.550000 +v -0.025000 -0.601364 -0.402078 +v -0.025000 -0.601364 -0.044706 +v -0.025000 -0.398636 -0.044706 +v -0.025000 -0.398636 -0.402078 +v -0.374620 -0.412671 -0.045097 +v -0.374620 -0.587329 -0.047815 +v -0.374620 -0.587329 -0.388044 +v -0.374620 -0.412671 -0.388044 +v -0.005099 -0.601364 -0.402078 +v -0.005099 -0.601364 -0.044706 +v -0.005099 -0.398636 -0.044706 +v -0.005099 -0.398636 -0.402078 +v -0.005099 -0.587329 -0.388044 +v -0.005099 -0.587329 -0.047815 +v -0.005099 -0.412671 -0.045097 +v -0.005099 -0.412671 -0.388044 +v -0.017305 -0.419472 -0.044438 +v -0.017305 -0.594130 -0.044438 +v -0.025000 -0.975000 -0.517611 +v -0.025000 -0.975000 -0.050000 +v -0.025000 -0.601364 -0.402078 +v -0.025000 -0.601364 -0.044706 +v -0.025000 -0.025000 -0.050000 +v -0.025000 -0.025000 -0.517611 +v -0.025000 -0.398636 -0.044706 +v -0.025000 -0.398636 -0.402078 +v -0.925000 -0.075000 -1.550000 +v -0.075000 -0.075000 -1.550000 +v -0.075000 -0.925000 -1.550000 +v -0.925000 -0.925000 -1.550000 +v -0.975000 -0.025000 -1.550000 +v -0.025000 -0.025000 -1.550000 +v -0.025000 -0.975000 -1.550000 +v -0.975000 -0.975000 -1.550000 +v -0.975000 -0.025000 -1.600000 +v -0.025000 -0.025000 -1.600000 +v -0.025000 -0.975000 -1.600000 +v -0.975000 -0.975000 -1.600000 +v -0.925000 -0.075000 -1.600000 +v -0.075000 -0.075000 -1.600000 +v -0.075000 -0.925000 -1.600000 +v -0.925000 -0.925000 -1.600000 +v 0.160449 -0.127295 -1.107365 +v 0.160449 -0.127295 -1.287365 +v -0.026426 -0.127295 -1.107365 +v -0.026426 -0.127295 -1.287365 +v 0.160449 -0.427295 -1.107365 +v 0.160449 -0.427295 -1.287365 +v -0.026426 -0.427295 -1.107365 +v -0.026426 -0.427295 -1.287365 +v -0.026426 -0.127295 -1.287365 +v -0.026426 -0.127295 -1.107365 +v 0.160449 -0.127295 -1.287365 +v 0.160449 -0.127295 -1.107365 +v 0.160449 -0.427295 -1.287365 +v 0.160449 -0.427295 -1.107365 +v 0.160449 -0.127295 -1.287365 +v 0.160449 -0.127295 -1.107365 +v -0.026426 -0.427295 -1.287365 +v -0.026426 -0.427295 -1.107365 +v 0.160449 -0.427295 -1.287365 +v 0.160449 -0.427295 -1.107365 +v -0.157753 -0.144986 -1.539514 +v -0.157753 -0.144986 -1.637282 +v -0.240677 -0.144986 -1.539514 +v -0.240677 -0.144986 -1.637282 +v -0.157753 -0.328413 -1.539514 +v -0.157753 -0.328413 -1.637282 +v -0.240677 -0.328413 -1.539514 +v -0.240677 -0.328413 -1.637282 +v -0.480538 -0.445573 -1.455033 +v -0.480538 -0.445573 -1.817243 +v -0.732419 -0.445573 -1.455033 +v -0.732419 -0.445573 -1.817243 +v -0.480538 -0.823959 -1.455033 +v -0.480538 -0.823959 -1.685969 +v -0.732419 -0.823959 -1.455033 +v -0.732419 -0.823959 -1.685969 +v -0.157753 -0.144986 -1.539514 +v -0.157753 -0.144986 -1.637282 +v -0.240677 -0.144986 -1.539514 +v -0.240677 -0.144986 -1.637282 +v -0.157753 -0.328413 -1.539514 +v -0.157753 -0.328413 -1.637282 +v -0.240677 -0.328413 -1.539514 +v -0.240677 -0.328413 -1.637282 +v -0.026426 -0.585532 -1.287365 +v -0.026426 -0.585532 -1.107365 +v 0.160449 -0.585532 -1.287365 +v 0.160449 -0.585532 -1.107365 +v 0.160449 -0.885532 -1.287365 +v 0.160449 -0.885532 -1.107365 +v 0.160449 -0.585532 -1.287365 +v 0.160449 -0.585532 -1.107365 +v -0.026426 -0.885532 -1.287365 +v -0.026426 -0.885532 -1.107365 +v 0.160449 -0.885532 -1.287365 +v 0.160449 -0.885532 -1.107365 +v 0.160449 -0.586497 -0.622366 +v 0.160449 -0.586497 -0.802366 +v -0.026426 -0.586497 -0.622366 +v -0.026426 -0.586497 -0.802366 +v 0.160449 -0.886497 -0.802366 +v 0.160449 -0.886497 -0.622366 +v 0.160449 -0.586497 -0.802366 +v 0.160449 -0.586497 -0.622366 +v -0.026426 -0.886497 -0.802366 +v -0.026426 -0.886497 -0.622366 +v 0.160449 -0.886497 -0.802366 +v 0.160449 -0.886497 -0.622366 +v 0.160449 -0.126028 -0.622366 +v 0.160449 -0.126028 -0.802366 +v -0.026426 -0.126028 -0.622366 +v -0.026426 -0.126028 -0.802366 +v 0.160449 -0.426028 -0.802366 +v 0.160449 -0.426028 -0.622366 +v 0.160449 -0.126028 -0.802366 +v 0.160449 -0.126028 -0.622366 +v -0.026426 -0.426028 -0.802366 +v -0.026426 -0.426028 -0.622366 +v 0.160449 -0.426028 -0.802366 +v 0.160449 -0.426028 -0.622366 +v -0.026426 -0.585532 -1.287365 +v -0.026426 -0.585532 -1.107365 +v 0.160449 -0.585532 -1.287365 +v 0.160449 -0.585532 -1.107365 +v 0.160449 -0.885532 -1.287365 +v 0.160449 -0.885532 -1.107365 +v 0.160449 -0.585532 -1.287365 +v 0.160449 -0.585532 -1.107365 +v -0.026426 -0.885532 -1.287365 +v -0.026426 -0.885532 -1.107365 +v 0.160449 -0.885532 -1.287365 +v 0.160449 -0.885532 -1.107365 +v 0.160449 -0.586497 -0.622366 +v 0.160449 -0.586497 -0.802366 +v -0.026426 -0.586497 -0.622366 +v -0.026426 -0.586497 -0.802366 +v 0.160449 -0.886497 -0.802366 +v 0.160449 -0.886497 -0.622366 +v 0.160449 -0.586497 -0.802366 +v 0.160449 -0.586497 -0.622366 +v -0.026426 -0.886497 -0.802366 +v -0.026426 -0.886497 -0.622366 +v 0.160449 -0.886497 -0.802366 +v 0.160449 -0.886497 -0.622366 +v 0.160449 -0.126028 -0.622366 +v 0.160449 -0.126028 -0.802366 +v -0.026426 -0.126028 -0.622366 +v -0.026426 -0.126028 -0.802366 +v 0.160449 -0.426028 -0.802366 +v 0.160449 -0.426028 -0.622366 +v 0.160449 -0.126028 -0.802366 +v 0.160449 -0.126028 -0.622366 +v -0.026426 -0.426028 -0.802366 +v -0.026426 -0.426028 -0.622366 +v 0.160449 -0.426028 -0.802366 +v 0.160449 -0.426028 -0.622366 +v 0.160449 -0.584850 -1.107365 +v -0.026426 -0.584850 -1.107365 +v 0.160449 -0.884850 -1.107365 +v -0.026426 -0.884850 -1.107365 +v 0.160449 -0.127295 -0.622373 +v -0.026426 -0.127295 -0.622373 +v 0.160449 -0.427295 -0.622373 +v -0.026426 -0.427295 -0.622373 +v 0.160449 -0.584850 -0.622373 +v -0.026426 -0.584850 -0.622373 +v 0.160449 -0.884850 -0.622373 +v -0.026426 -0.884850 -0.622373 +vt 0.014847 0.403582 +vt 0.153703 0.694145 +vt 0.014847 0.694145 +vt 0.034115 0.694145 +vt 0.048963 1.000000 +vt 0.034115 1.000000 +vt 0.047359 0.372997 +vt 0.032511 0.067142 +vt 0.047358 0.067142 +vt 0.048963 0.694145 +vt 0.063810 1.000000 +vt 0.048963 1.000000 +vt 0.019268 0.694145 +vt 0.034115 1.000000 +vt 0.019268 1.000000 +vt 0.710478 0.701791 +vt 1.000000 0.694145 +vt 0.992576 0.701791 +vt 1.000000 1.000000 +vt 0.992576 0.992353 +vt 0.703054 1.000000 +vt 0.710478 0.992354 +vt 0.703054 0.694145 +vt 1.000000 0.051849 +vt 0.717901 0.357704 +vt 0.717901 0.051849 +vt 0.047359 0.082435 +vt 0.186214 0.372997 +vt 0.047359 0.372997 +vt 0.186214 0.082435 +vt 0.325069 0.372997 +vt 0.186214 0.372997 +vt 1.000000 1.000000 +vt 1.000000 1.000000 +vt 1.000000 1.000000 +vt 0.703054 0.694145 +vt 0.413541 0.701796 +vt 0.406108 0.694145 +vt 0.703054 1.000000 +vt 0.695640 0.701796 +vt 0.406108 1.000000 +vt 0.695640 0.992358 +vt 0.413541 0.992358 +vt 0.004421 0.885721 +vt 0.002849 0.709438 +vt 0.004421 0.823716 +vt 0.118100 0.779467 +vt 0.115894 0.721754 +vt 0.118100 0.726047 +vt 1.000000 1.000000 +vt 1.000000 1.000000 +vt 0.119844 0.783760 +vt 0.124009 0.890693 +vt 0.124009 0.890693 +vt 0.509125 0.003716 +vt 0.515034 0.113020 +vt 0.509125 0.113020 +vt 0.616064 0.113020 +vt 0.717901 0.000000 +vt 0.717901 0.113020 +vt 1.000000 1.000000 +vt 1.000000 1.000000 +vt 0.119842 0.995708 +vt 0.124009 0.890696 +vt 0.124009 1.000000 +vt 0.067977 0.995708 +vt 0.063810 0.890696 +vt 0.067977 0.890815 +vt 0.063810 1.000000 +vt 0.515034 0.113020 +vt 0.616064 0.000000 +vt 0.616064 0.113020 +vt 0.118100 0.721754 +vt 0.124009 0.783760 +vt 0.118100 0.783760 +vt 0.509125 0.113020 +vt 0.503215 0.003716 +vt 0.509125 0.003716 +vt 0.115815 0.777387 +vt 0.115815 0.723967 +vt 0.431190 0.196713 +vt 0.465497 0.082435 +vt 0.465497 0.372997 +vt 0.465497 0.113020 +vt 0.717901 0.372997 +vt 0.465497 0.372997 +vt 0.717901 0.372997 +vt 0.435802 0.678852 +vt 0.435802 0.372997 +vt 1.000000 0.372997 +vt 0.717901 0.678852 +vt 0.717901 0.372997 +vt 0.435802 0.372997 +vt 0.153703 0.678852 +vt 0.153703 0.372997 +vt 0.717901 0.678852 +vt 0.435802 0.694145 +vt 0.017664 0.372997 +vt 0.002817 0.113020 +vt 0.017664 0.113020 +vt 1.000000 0.357704 +vt 0.717901 0.372997 +vt 0.032511 0.372997 +vt 0.017664 0.372997 +vt 0.138856 0.724730 +vt 0.406108 0.709437 +vt 0.391260 0.724730 +vt 0.406108 1.000000 +vt 0.391260 0.984707 +vt 0.124009 1.000000 +vt 0.138856 0.984707 +vt 0.124009 0.709438 +vt 0.014847 0.694145 +vt 0.000000 0.434168 +vt 0.014847 0.434168 +vt 1.000000 0.678852 +vt 0.717901 0.694145 +vt 0.435802 0.678852 +vt 0.153703 0.694145 +vt 0.004421 0.740023 +vt 0.019268 1.000000 +vt 0.004421 1.000000 +vt 0.316450 0.067652 +vt 0.252222 0.005787 +vt 0.316449 0.005787 +vt 0.483784 0.067652 +vt 0.419557 0.005787 +vt 0.483784 0.005787 +vt 0.419557 0.067652 +vt 0.248111 0.067096 +vt 0.165675 0.015745 +vt 0.248111 0.015745 +vt 0.252222 0.005787 +vt 0.316450 0.067652 +vt 0.316449 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.419557 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.483784 0.005787 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.525322 0.836366 +vt 0.586878 0.919862 +vt 0.525322 0.919862 +vt 0.552285 0.749140 +vt 0.608723 0.836366 +vt 0.552285 0.836366 +vt 0.586878 0.894429 +vt 0.643316 0.836366 +vt 0.643316 0.894429 +vt 0.520203 0.749140 +vt 0.463765 0.836366 +vt 0.463765 0.749140 +vt 0.463765 0.836366 +vt 0.525322 0.928691 +vt 0.463765 0.928691 +vt 0.892836 0.808021 +vt 0.844939 0.752099 +vt 0.892836 0.752099 +vt 0.884262 0.808021 +vt 0.827791 0.912939 +vt 0.827791 0.808021 +vt 0.940733 0.808021 +vt 0.892836 0.752099 +vt 0.940733 0.752099 +vt 0.884262 0.912939 +vt 0.940733 0.808021 +vt 0.940733 0.912939 +vt 0.779894 0.808021 +vt 0.827791 0.912939 +vt 0.779894 0.912939 +vt 0.252222 0.005787 +vt 0.316450 0.067652 +vt 0.316449 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.419557 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.483784 0.005787 +vt 0.252222 0.005787 +vt 0.316450 0.067652 +vt 0.316449 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.419557 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.483784 0.005787 +vt 0.252222 0.005787 +vt 0.316450 0.067652 +vt 0.316449 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.419557 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.483784 0.005787 +vt 0.316450 0.067652 +vt 0.252222 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.316449 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.419557 0.005787 +vt 0.483784 0.005787 +vt 0.316450 0.067652 +vt 0.252222 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.316449 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.419557 0.005787 +vt 0.483784 0.005787 +vt 0.316450 0.067652 +vt 0.252222 0.005787 +vt 0.316449 0.005787 +vt 0.419557 0.067652 +vt 0.316449 0.005787 +vt 0.419557 0.005787 +vt 0.483784 0.067652 +vt 0.419557 0.005787 +vt 0.483784 0.005787 +vt 0.248111 0.067096 +vt 0.165675 0.015745 +vt 0.248111 0.015745 +vt 0.248111 0.067096 +vt 0.165675 0.015745 +vt 0.248111 0.015745 +vt 0.248111 0.067096 +vt 0.165675 0.015745 +vt 0.248111 0.015745 +vt 0.153703 0.403582 +vt 0.048963 0.694145 +vt 0.032511 0.372997 +vt 0.063810 0.694145 +vt 0.034115 0.694145 +vt 0.186214 0.082435 +vt 0.325069 0.082435 +vt 0.002849 1.000000 +vt 0.115894 0.783760 +vt 1.000000 1.000000 +vt 0.119840 0.890696 +vt 0.067976 0.890695 +vt 0.067979 0.783760 +vt 0.063810 0.890691 +vt 0.063810 0.890691 +vt 0.515034 0.003716 +vt 0.616064 0.000000 +vt 0.119842 0.891647 +vt 0.515034 0.000000 +vt 0.124009 0.721754 +vt 0.503215 0.113020 +vt 0.326641 0.372997 +vt 0.431190 0.258718 +vt 0.325069 0.258718 +vt 0.325069 0.196713 +vt 0.326641 0.082435 +vt 0.717901 0.113020 +vt 0.717901 0.694145 +vt 0.002817 0.372997 +vt 1.000000 0.372997 +vt 0.032511 0.113020 +vt 0.000000 0.694145 +vt 1.000000 0.694145 +vt 0.435802 0.694145 +vt 0.019268 0.740023 +vt 0.252222 0.067652 +vt 0.165675 0.067096 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.586878 0.836366 +vt 0.640804 0.749140 +vt 0.586878 0.836366 +vt 0.552285 0.836366 +vt 0.844939 0.808021 +vt 0.884262 0.912939 +vt 0.892836 0.808021 +vt 0.884262 0.808021 +vt 0.827791 0.808021 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.252222 0.067652 +vt 0.316450 0.067652 +vt 0.419557 0.067652 +vt 0.165675 0.067096 +vt 0.165675 0.067096 +vt 0.165675 0.067096 +vn 0.0000 -1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 0.6720 -0.7406 +vn 0.6720 0.0000 -0.7406 +vn 0.0000 -0.6720 -0.7406 +vn -0.6720 0.0000 -0.7406 +vn 0.7071 0.0000 -0.7071 +vn 0.0000 -0.3278 -0.9448 +vn -0.0178 0.4677 -0.8837 +vn -0.0123 0.0000 -0.9999 +vn -0.0201 0.0156 -0.9997 +vn -0.0109 -0.4677 -0.8838 +usemtl Material.001 +s off +f 8/1/1 41/2/1 42/3/1 +f 3/4/2 12/5/2 4/6/2 +f 2/7/3 10/8/3 1/9/3 +f 4/10/1 11/11/1 2/12/1 +f 1/13/4 9/14/4 3/15/4 +f 7/16/5 10/17/5 45/18/5 +f 45/18/5 11/19/5 42/20/5 +f 42/20/5 12/21/5 8/22/5 +f 8/22/5 9/23/5 7/16/5 +f 22/24/1 55/25/1 21/26/1 +f 45/27/4 13/28/4 7/29/4 +f 7/30/2 14/31/2 8/32/2 +f 43/33/6 26/34/6 23/35/6 +f 16/36/7 19/37/7 15/38/7 +f 17/39/8 20/40/8 16/36/8 +f 18/41/9 21/42/9 17/39/9 +f 15/38/10 22/43/10 18/41/10 +f 47/44/2 42/45/2 44/46/2 +f 5/47/3 44/48/3 6/49/3 +f 48/50/6 25/51/6 26/34/6 +f 27/52/6 25/53/6 47/54/6 +f 25/55/4 34/56/4 26/57/4 +f 30/58/1 37/59/1 27/60/1 +f 44/61/6 23/35/6 24/62/6 +f 35/63/3 32/64/3 31/65/3 +f 38/66/3 33/67/3 37/68/3 +f 35/63/3 34/69/3 38/66/3 +f 28/70/4 35/71/4 29/72/4 +f 26/73/5 31/74/5 23/75/5 +f 23/76/1 32/77/1 24/78/1 +f 6/49/11 39/79/11 40/80/11 +f 43/81/3 41/82/3 46/83/3 +f 51/84/5 49/85/5 50/86/5 +f 20/87/4 53/88/4 19/89/4 +f 19/90/2 56/91/2 22/92/2 +f 21/93/3 54/94/3 20/95/3 +f 54/96/4 57/97/4 53/88/4 +f 52/98/3 61/99/3 49/100/3 +f 56/101/1 59/102/1 55/25/1 +f 49/100/1 62/103/1 50/104/1 +f 61/105/5 58/106/5 62/107/5 +f 62/107/5 59/108/5 63/109/5 +f 63/109/5 60/110/5 64/111/5 +f 64/111/5 57/112/5 61/105/5 +f 50/113/2 63/114/2 51/115/2 +f 53/116/2 60/117/2 56/91/2 +f 55/118/3 58/119/3 54/94/3 +f 51/120/4 64/121/4 52/122/4 +f 66/123/4 67/124/4 65/125/4 +f 72/126/1 69/127/1 71/128/1 +f 70/129/3 65/125/3 69/127/3 +f 65/130/5 71/131/5 67/132/5 +f 74/133/1 75/134/1 76/135/1 +f 80/136/2 77/137/2 78/138/2 +f 84/139/4 81/140/4 82/141/4 +f 86/142/4 87/143/4 85/144/4 +f 88/145/2 91/146/2 87/143/2 +f 92/147/1 89/148/1 91/146/1 +f 90/149/3 85/144/3 89/148/3 +f 88/145/5 90/149/5 92/147/5 +f 94/150/4 95/151/4 93/152/4 +f 95/153/2 100/154/2 99/155/2 +f 100/156/1 97/157/1 99/158/1 +f 98/159/3 93/160/3 97/161/3 +f 96/162/12 98/163/12 100/164/12 +f 102/165/4 103/166/4 101/167/4 +f 104/168/2 107/169/2 103/170/2 +f 108/171/1 105/172/1 107/173/1 +f 106/174/3 101/175/3 105/176/3 +f 104/177/5 106/178/5 108/179/5 +f 110/180/1 111/181/1 112/182/1 +f 116/183/2 113/184/2 114/185/2 +f 120/186/4 117/187/4 118/188/4 +f 123/189/1 122/190/1 121/191/1 +f 128/192/2 125/193/2 126/194/2 +f 132/195/4 129/196/4 130/197/4 +f 135/198/1 134/199/1 133/200/1 +f 140/201/2 137/202/2 138/203/2 +f 144/204/4 141/205/4 142/206/4 +f 147/207/4 146/208/4 148/209/4 +f 149/210/3 152/211/3 150/212/3 +f 153/213/1 156/214/1 154/215/1 +f 158/216/4 159/217/4 157/218/4 +f 161/219/3 164/220/3 162/221/3 +f 165/222/1 168/223/1 166/224/1 +f 170/225/4 171/226/4 169/227/4 +f 173/228/3 176/229/3 174/230/3 +f 177/231/1 180/232/1 178/233/1 +f 181/234/5 184/235/5 182/236/5 +f 185/237/5 188/238/5 186/239/5 +f 189/240/5 192/241/5 190/242/5 +f 8/1/1 14/243/1 41/2/1 +f 3/4/2 9/244/2 12/5/2 +f 2/7/3 11/245/3 10/8/3 +f 4/10/1 12/246/1 11/11/1 +f 1/13/4 10/247/4 9/14/4 +f 7/16/5 9/23/5 10/17/5 +f 45/18/5 10/17/5 11/19/5 +f 42/20/5 11/19/5 12/21/5 +f 8/22/5 12/21/5 9/23/5 +f 22/24/1 56/101/1 55/25/1 +f 45/27/4 46/248/4 13/28/4 +f 7/30/2 13/249/2 14/31/2 +f 43/33/6 48/50/6 26/34/6 +f 16/36/7 20/40/7 19/37/7 +f 17/39/8 21/42/8 20/40/8 +f 18/41/9 22/43/9 21/42/9 +f 15/38/10 19/37/10 22/43/10 +f 47/44/2 45/250/2 42/45/2 +f 5/47/3 47/251/3 44/48/3 +f 48/50/6 47/252/6 25/51/6 +f 47/54/13 5/253/13 27/52/13 +f 5/253/14 6/254/14 28/255/14 +f 44/256/6 24/257/6 28/255/6 +f 5/253/15 28/255/15 27/52/15 +f 6/254/16 44/256/16 28/255/16 +f 25/55/4 33/258/4 34/56/4 +f 30/58/1 38/259/1 37/59/1 +f 44/61/6 43/33/6 23/35/6 +f 35/63/3 36/260/3 32/64/3 +f 38/66/3 34/69/3 33/67/3 +f 35/63/3 31/65/3 34/69/3 +f 28/70/4 36/261/4 35/71/4 +f 26/73/5 34/262/5 31/74/5 +f 23/76/1 31/263/1 32/77/1 +f 6/49/11 5/47/11 39/79/11 +f 46/83/3 45/264/3 48/265/3 +f 45/264/3 47/266/3 48/265/3 +f 44/267/3 42/268/3 43/81/3 +f 42/268/3 41/82/3 43/81/3 +f 46/83/3 48/265/3 43/81/3 +f 51/84/5 52/269/5 49/85/5 +f 20/87/4 54/96/4 53/88/4 +f 19/90/2 53/116/2 56/91/2 +f 21/93/3 55/118/3 54/94/3 +f 54/96/4 58/270/4 57/97/4 +f 52/98/3 64/271/3 61/99/3 +f 56/101/1 60/272/1 59/102/1 +f 49/100/1 61/273/1 62/103/1 +f 61/105/5 57/112/5 58/106/5 +f 62/107/5 58/106/5 59/108/5 +f 63/109/5 59/108/5 60/110/5 +f 64/111/5 60/110/5 57/112/5 +f 50/113/2 62/274/2 63/114/2 +f 53/116/2 57/275/2 60/117/2 +f 55/118/3 59/276/3 58/119/3 +f 51/120/4 63/277/4 64/121/4 +f 66/123/4 68/278/4 67/124/4 +f 72/126/1 70/129/1 69/127/1 +f 70/129/3 66/123/3 65/125/3 +f 65/130/5 69/279/5 71/131/5 +f 74/133/1 73/280/1 75/134/1 +f 80/136/2 79/281/2 77/137/2 +f 84/139/4 83/282/4 81/140/4 +f 86/142/4 88/145/4 87/143/4 +f 88/145/2 92/147/2 91/146/2 +f 92/147/1 90/149/1 89/148/1 +f 90/149/3 86/142/3 85/144/3 +f 88/145/5 86/142/5 90/149/5 +f 94/150/4 96/283/4 95/151/4 +f 95/153/2 96/284/2 100/154/2 +f 100/156/1 98/285/1 97/157/1 +f 98/159/3 94/286/3 93/160/3 +f 96/162/12 94/150/12 98/163/12 +f 102/165/4 104/287/4 103/166/4 +f 104/168/2 108/288/2 107/169/2 +f 108/171/1 106/289/1 105/172/1 +f 106/174/3 102/290/3 101/175/3 +f 104/177/5 102/291/5 106/178/5 +f 110/180/1 109/292/1 111/181/1 +f 116/183/2 115/293/2 113/184/2 +f 120/186/4 119/294/4 117/187/4 +f 123/189/1 124/295/1 122/190/1 +f 128/192/2 127/296/2 125/193/2 +f 132/195/4 131/297/4 129/196/4 +f 135/198/1 136/298/1 134/199/1 +f 140/201/2 139/299/2 137/202/2 +f 144/204/4 143/300/4 141/205/4 +f 147/207/4 145/301/4 146/208/4 +f 149/210/3 151/302/3 152/211/3 +f 153/213/1 155/303/1 156/214/1 +f 158/216/4 160/304/4 159/217/4 +f 161/219/3 163/305/3 164/220/3 +f 165/222/1 167/306/1 168/223/1 +f 170/225/4 172/307/4 171/226/4 +f 173/228/3 175/308/3 176/229/3 +f 177/231/1 179/309/1 180/232/1 +f 181/234/5 183/310/5 184/235/5 +f 185/237/5 187/311/5 188/238/5 +f 189/240/5 191/312/5 192/241/5 diff --git a/CarCrimeCity/Part2/assets/buildings/udxs_building1.png b/CarCrimeCity/Part2/assets/buildings/udxs_building1.png new file mode 100644 index 0000000..746be5b Binary files /dev/null and b/CarCrimeCity/Part2/assets/buildings/udxs_building1.png differ diff --git a/CarCrimeCity/Part2/assets/buildings/unit_building.blend b/CarCrimeCity/Part2/assets/buildings/unit_building.blend new file mode 100644 index 0000000..bcc3b6c Binary files /dev/null and b/CarCrimeCity/Part2/assets/buildings/unit_building.blend differ diff --git a/CarCrimeCity/Part2/assets/buildings/unit_building.blend1 b/CarCrimeCity/Part2/assets/buildings/unit_building.blend1 new file mode 100644 index 0000000..f0ef2f6 Binary files /dev/null and b/CarCrimeCity/Part2/assets/buildings/unit_building.blend1 differ diff --git a/CarCrimeCity/Part2/assets/buildings/unit_building.obj b/CarCrimeCity/Part2/assets/buildings/unit_building.obj new file mode 100644 index 0000000..3683256 --- /dev/null +++ b/CarCrimeCity/Part2/assets/buildings/unit_building.obj @@ -0,0 +1,26 @@ +# Blender v2.79 (sub 0) OBJ File: 'unit_building.blend' +# www.blender.org +v 1.0000 1.000 -0.000 +v 1.0000 1.0 -0.50 +v 0.0000 1.00 -0.000 +v 0.0000 1.000 -0.5 +v 1.0 0.00 0.000 +v 1.0 0.00000 -0.5 +v -0.000081 0.004528 0.004407 +v -0.000081 0.000101 -0.495573 +vn 0.0002 1.0000 -0.0089 +vn -1.0000 0.0002 -0.0000 +vn -0.0002 -1.0000 0.0089 +vn 1.0000 -0.0002 0.0000 +vn -0.0000 -0.0089 -1.0000 +s off +f 2//1 3//1 1//1 +f 4//2 7//2 3//2 +f 8//3 5//3 7//3 +f 6//4 1//4 5//4 +f 4//5 6//5 8//5 +f 2//1 4//1 3//1 +f 4//2 8//2 7//2 +f 8//3 6//3 5//3 +f 6//4 2//4 1//4 +f 4//5 2//5 6//5 diff --git a/CarCrimeCity/Part2/assets/cities/example1.city b/CarCrimeCity/Part2/assets/cities/example1.city new file mode 100644 index 0000000..47dfb0b Binary files /dev/null and b/CarCrimeCity/Part2/assets/cities/example1.city differ diff --git a/CarCrimeCity/Part2/assets/config.lua b/CarCrimeCity/Part2/assets/config.lua new file mode 100644 index 0000000..ec9e790 --- /dev/null +++ b/CarCrimeCity/Part2/assets/config.lua @@ -0,0 +1,50 @@ + + +-- Size of pixel +PixelWidth = 2 +PixelHeight = 2 + +-- Size of display window in pixels +ScreenWidth = 768 +ScreenHeight = 480 +--ScreenWidth = 384 +--ScreenHeight = 240 + +FullScreen = false + +-- Default city parameters +DefaultMapWidth = 64 +DefaultMapHeight = 32 +--DefaultCityFile = "assets/cities/example1.city" + + +-- Textures used by various game systems +Textures = {} +Textures[1] = {"Grass", "assets/system/grass1.png"} +Textures[2] = {"AllRoads", "assets/system/roads4.png"} +Textures[3] = {"Water", "assets/system/water1.png"} +Textures[4] = {"Clouds", "assets/system/clouds2.png"} +Textures[5] = {"WaterSide", "assets/system/waterside1.png"} +Textures[6] = {"Smoke", "assets/system/skidsmoke1.png"} + +-- Buildings +Buildings = {} +Buildings[1] = {"javidx9", "UnitBuilding_1", "assets/buildings/unit_building.obj", "", + 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0} +Buildings[2] = {"UDXS", "Apartments_1", "assets/buildings/udxs_building1.obj", "assets/buildings/udxs_building1.png", + 0.0, 0.0, 0.0, 1.0, 1.0, 0.5, 1.0, 1.0, 0.0} + +Vehicles = {} +Vehicles[1] = {"JustinRM", "Sedan", "assets/vehicles/CarCrime_Sedan.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 1.5708, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} +Vehicles[2] = {"JustinRM", "SUV", "assets/vehicles/CarCrime_SUV.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 0.0, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} +Vehicles[3] = {"JustinRM", "TruckCab", "assets/vehicles/CarCrime_Truck_Cab.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 0.0, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} +Vehicles[4] = {"JustinRM", "TruckTrailer", "assets/vehicles/CarCrime_Truck_Trailer.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 0.0, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} +Vehicles[5] = {"JustinRM", "UTE", "assets/vehicles/CarCrime_Ute.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 0.0, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} +Vehicles[6] = {"JustinRM", "Wagon", "assets/vehicles/CarCrime_Wahon.obj", "assets/vehicles/CarTex_256.png", + 0.0, 0.0, 0.0, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0} + diff --git a/CarCrimeCity/Part2/assets/system/car_top.png b/CarCrimeCity/Part2/assets/system/car_top.png new file mode 100644 index 0000000..ad89ae4 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/car_top.png differ diff --git a/CarCrimeCity/Part2/assets/system/car_top3.png b/CarCrimeCity/Part2/assets/system/car_top3.png new file mode 100644 index 0000000..25db6a7 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/car_top3.png differ diff --git a/CarCrimeCity/Part2/assets/system/ccctitle1.png b/CarCrimeCity/Part2/assets/system/ccctitle1.png new file mode 100644 index 0000000..fd02a35 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/ccctitle1.png differ diff --git a/CarCrimeCity/Part2/assets/system/clouds1.png b/CarCrimeCity/Part2/assets/system/clouds1.png new file mode 100644 index 0000000..e0f20f4 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/clouds1.png differ diff --git a/CarCrimeCity/Part2/assets/system/clouds2.png b/CarCrimeCity/Part2/assets/system/clouds2.png new file mode 100644 index 0000000..400f99a Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/clouds2.png differ diff --git a/CarCrimeCity/Part2/assets/system/grass1.png b/CarCrimeCity/Part2/assets/system/grass1.png new file mode 100644 index 0000000..bb1c9bf Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/grass1.png differ diff --git a/CarCrimeCity/Part2/assets/system/roads1.png b/CarCrimeCity/Part2/assets/system/roads1.png new file mode 100644 index 0000000..24dce8c Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/roads1.png differ diff --git a/CarCrimeCity/Part2/assets/system/roads2.png b/CarCrimeCity/Part2/assets/system/roads2.png new file mode 100644 index 0000000..e2b6231 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/roads2.png differ diff --git a/CarCrimeCity/Part2/assets/system/roads3.png b/CarCrimeCity/Part2/assets/system/roads3.png new file mode 100644 index 0000000..95b8752 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/roads3.png differ diff --git a/CarCrimeCity/Part2/assets/system/roads4.png b/CarCrimeCity/Part2/assets/system/roads4.png new file mode 100644 index 0000000..04d56a4 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/roads4.png differ diff --git a/CarCrimeCity/Part2/assets/system/skidsmoke1.png b/CarCrimeCity/Part2/assets/system/skidsmoke1.png new file mode 100644 index 0000000..78c9b3d Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/skidsmoke1.png differ diff --git a/CarCrimeCity/Part2/assets/system/water1.png b/CarCrimeCity/Part2/assets/system/water1.png new file mode 100644 index 0000000..9194ae0 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/water1.png differ diff --git a/CarCrimeCity/Part2/assets/system/waterside1.png b/CarCrimeCity/Part2/assets/system/waterside1.png new file mode 100644 index 0000000..9cb1f44 Binary files /dev/null and b/CarCrimeCity/Part2/assets/system/waterside1.png differ diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_SUV.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_SUV.obj new file mode 100644 index 0000000..0952689 --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_SUV.obj @@ -0,0 +1,121 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v 0.600000 -0.400000 -1.700000 +v 0.600000 1.700000 -1.700000 +v -0.600000 -0.400000 -1.700000 +v -0.600000 1.700000 -1.700000 +v -0.800000 2.000000 -1.100000 +v 0.800000 2.000000 -1.100000 +v -0.800000 2.000000 -1.100000 +v 0.800000 2.000000 -1.100000 +v -0.800000 -1.000000 -0.950000 +v 0.800000 -1.000000 -0.950000 +v -0.800000 -2.000000 -0.900000 +v 0.800000 -2.000000 -0.900000 +v -0.800000 2.000000 -0.400000 +v 0.800000 2.000000 -0.400000 +v -0.800000 -2.000000 -0.400000 +v 0.800000 -2.000000 -0.400000 +v 0.800000 -2.000000 -0.400000 +v 0.800000 2.000000 -0.400000 +v 0.800000 -2.000000 -0.900000 +v 0.800000 2.000000 -1.100000 +v -0.800000 -2.000000 -0.900000 +v -0.800000 2.000000 -1.100000 +v -0.800000 -2.000000 -0.400000 +v -0.800000 2.000000 -0.400000 +v 0.780000 1.200000 -0.400000 +v 0.780000 1.500000 -0.400000 +v 0.780000 1.400000 0.000000 +v 0.780000 1.000000 0.000000 +v 0.780000 0.900000 -0.400000 +v 0.780000 -1.100000 -0.400000 +v 0.780000 -0.800000 -0.400000 +v 0.780000 -0.900000 0.000000 +v 0.780000 -1.300000 0.000000 +v 0.780000 -1.400000 -0.400000 +v -0.780000 -1.100000 -0.400000 +v -0.780000 -1.400000 -0.400000 +v -0.780000 -1.300000 0.000000 +v -0.780000 -0.900000 0.000000 +v -0.780000 -0.800000 -0.400000 +v -0.780000 1.200000 -0.400000 +v -0.780000 0.900000 -0.400000 +v -0.780000 1.000000 0.000000 +v -0.780000 1.400000 0.000000 +v -0.780000 1.500000 -0.400000 +vt 0.564792 0.689981 +vt 0.564792 0.953949 +vt 0.338554 0.953949 +vt 0.338554 0.689981 +vt 0.334296 0.692438 +vt 0.334296 0.954445 +vt 0.203294 0.986197 +vt 0.203294 0.656186 +vt 0.695616 0.984433 +vt 0.572654 0.959219 +vt 0.695616 0.657719 +vt 0.572795 0.683358 +vt 0.941945 0.999442 +vt 0.694306 0.999442 +vt 0.941945 0.647349 +vt 0.694306 0.647349 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.331416 0.690927 +vt 0.238667 0.577426 +vt 0.563274 0.690927 +vt 0.735343 0.574985 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.743883 0.446331 +vt 0.779872 0.385852 +vt 0.817351 0.446331 +vt 0.853830 0.385852 +vt 0.890820 0.446331 +s off +f 1/1 3/2 4/3 +f 2/4 1/1 4/3 +f 2/5 4/6 5/7 +f 5/7 6/8 2/5 +f 9/9 3/10 10/11 +f 3/10 1/12 10/11 +f 11/13 9/14 12/15 +f 10/16 12/15 9/14 +f 8/17 7/18 13/19 +f 13/19 14/20 8/17 +f 15/21 11/22 16/23 +f 12/24 16/23 11/22 +f 2/25 6/26 1/27 +f 10/28 1/27 6/26 +f 4/25 3/27 5/26 +f 9/28 5/26 3/27 +f 17/29 19/30 20/31 +f 18/32 17/29 20/31 +f 21/30 23/29 24/32 +f 22/31 21/30 24/32 +f 26/33 27/34 25/35 +f 27/34 28/36 25/35 +f 28/36 29/37 25/35 +f 31/38 32/39 30/40 +f 32/39 33/41 30/40 +f 33/41 34/42 30/40 +f 36/42 37/41 35/40 +f 37/41 38/39 35/40 +f 38/39 39/38 35/40 +f 41/37 42/36 40/35 +f 42/36 43/34 40/35 +f 43/34 44/33 40/35 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_Sedan.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Sedan.obj new file mode 100644 index 0000000..77daa43 --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Sedan.obj @@ -0,0 +1,127 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v 0.600000 -0.200000 -1.100000 +v 0.600000 1.000000 -1.100000 +v -0.600000 -0.200000 -1.100000 +v -0.600000 1.000000 -1.100000 +v -0.800000 1.400000 -0.700000 +v 0.800000 1.400000 -0.700000 +v -0.800000 2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -1.000000 -0.700000 +v 0.800000 -1.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v 0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v -0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v 0.800000 -2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.300000 +v -0.800000 2.000000 -0.300000 +v 0.780000 1.200000 -0.300000 +v 0.780000 1.500000 -0.300000 +v 0.780000 1.400000 0.000000 +v 0.780000 1.000000 0.000000 +v 0.780000 0.900000 -0.300000 +v 0.780000 -1.100000 -0.300000 +v 0.780000 -0.800000 -0.300000 +v 0.780000 -0.900000 0.000000 +v 0.780000 -1.300000 0.000000 +v 0.780000 -1.400000 -0.300000 +v -0.780000 -1.100000 -0.300000 +v -0.780000 -1.400000 -0.300000 +v -0.780000 -1.300000 0.000000 +v -0.780000 -0.900000 0.000000 +v -0.780000 -0.800000 -0.300000 +v -0.780000 1.200000 -0.300000 +v -0.780000 0.900000 -0.300000 +v -0.780000 1.000000 0.000000 +v -0.780000 1.400000 0.000000 +v -0.780000 1.500000 -0.300000 +vt 0.564792 0.689981 +vt 0.564792 0.953949 +vt 0.338554 0.953949 +vt 0.338554 0.689981 +vt 0.334296 0.692438 +vt 0.334296 0.954445 +vt 0.203294 0.986197 +vt 0.203294 0.656186 +vt 0.203326 0.657931 +vt 0.203326 0.986286 +vt 0.080997 0.986286 +vt 0.080997 0.657931 +vt 0.695616 0.984433 +vt 0.572654 0.959219 +vt 0.695616 0.657719 +vt 0.572795 0.683358 +vt 0.941945 0.999442 +vt 0.694306 0.999442 +vt 0.941945 0.647349 +vt 0.694306 0.647349 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.331416 0.690927 +vt 0.238667 0.577426 +vt 0.563274 0.690927 +vt 0.735343 0.574985 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.743883 0.446331 +vt 0.779872 0.385852 +vt 0.817351 0.446331 +vt 0.853830 0.385852 +vt 0.890820 0.446331 +s off +f 1/1 3/2 4/3 +f 2/4 1/1 4/3 +f 2/5 4/6 5/7 +f 5/7 6/8 2/5 +f 6/9 5/10 7/11 +f 7/11 8/12 6/9 +f 9/13 3/14 10/15 +f 3/14 1/16 10/15 +f 11/17 9/18 12/19 +f 10/20 12/19 9/18 +f 8/21 7/22 13/23 +f 13/23 14/24 8/21 +f 15/25 11/26 16/27 +f 12/28 16/27 11/26 +f 2/29 6/30 1/31 +f 10/32 1/31 6/30 +f 4/29 3/31 5/30 +f 9/32 5/30 3/31 +f 17/33 19/34 20/35 +f 18/36 17/33 20/35 +f 21/34 23/33 24/36 +f 22/35 21/34 24/36 +f 26/37 27/38 25/39 +f 27/38 28/40 25/39 +f 28/40 29/41 25/39 +f 31/42 32/43 30/44 +f 32/43 33/45 30/44 +f 33/45 34/46 30/44 +f 36/46 37/45 35/44 +f 37/45 38/43 35/44 +f 38/43 39/42 35/44 +f 41/41 42/40 40/39 +f 42/40 43/38 40/39 +f 43/38 44/37 40/39 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Cab.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Cab.obj new file mode 100644 index 0000000..f4806a9 --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Cab.obj @@ -0,0 +1,137 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v 0.600000 -1.900000 -1.500000 +v 0.600000 -1.000000 -1.500000 +v -0.600000 -1.900000 -1.500000 +v -0.600000 -1.000000 -1.500000 +v -0.800000 -0.900000 -0.700000 +v 0.800000 -0.900000 -0.700000 +v -0.800000 0.600000 -0.700000 +v 0.800000 0.600000 -0.700000 +v -0.800000 -2.400000 -0.700000 +v 0.800000 -2.400000 -0.700000 +v -0.800000 -2.400000 -0.700000 +v 0.800000 -2.400000 -0.700000 +v -0.800000 0.600000 -0.300000 +v 0.800000 0.600000 -0.300000 +v -0.800000 -2.400000 -0.300000 +v 0.800000 -2.400000 -0.300000 +v 0.800000 -2.400000 -0.300000 +v 0.800000 0.600000 -0.300000 +v 0.800000 -2.400000 -0.700000 +v 0.800000 0.600000 -0.700000 +v -0.800000 -2.400000 -0.700000 +v -0.800000 0.600000 -0.700000 +v -0.800000 -2.400000 -0.300000 +v -0.800000 0.600000 -0.300000 +v 0.780000 0.100000 -0.300000 +v 0.780000 0.400000 -0.300000 +v 0.780000 0.300000 0.000000 +v 0.780000 -0.100000 0.000000 +v 0.780000 -0.200000 -0.300000 +v 0.780000 -1.900000 -0.300000 +v 0.780000 -1.600000 -0.300000 +v 0.780000 -1.700000 0.000000 +v 0.780000 -2.100000 0.000000 +v 0.780000 -2.200000 -0.300000 +v -0.780000 -1.900000 -0.300000 +v -0.780000 -2.200000 -0.300000 +v -0.780000 -2.100000 0.000000 +v -0.780000 -1.700000 0.000000 +v -0.780000 -1.600000 -0.300000 +v -0.780000 0.100000 -0.300000 +v -0.780000 -0.200000 -0.300000 +v -0.780000 -0.100000 0.000000 +v -0.780000 0.300000 0.000000 +v -0.780000 0.400000 -0.300000 +v 0.780000 -0.600000 -0.300000 +v 0.780000 -0.300000 -0.300000 +v 0.780000 -0.400000 0.000000 +v 0.780000 -0.800000 0.000000 +v 0.780000 -0.900000 -0.300000 +v -0.780000 -0.600000 -0.300000 +v -0.780000 -0.900000 -0.300000 +v -0.780000 -0.800000 0.000000 +v -0.780000 -0.400000 0.000000 +v -0.780000 -0.300000 -0.300000 +vt 0.564792 0.689981 +vt 0.564792 0.953949 +vt 0.338554 0.953949 +vt 0.338554 0.689981 +vt 0.334296 0.692438 +vt 0.334296 0.954445 +vt 0.203294 0.986197 +vt 0.203294 0.656186 +vt 0.695616 0.984433 +vt 0.572654 0.959219 +vt 0.695616 0.657719 +vt 0.572795 0.683358 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.471796 0.690927 +vt 0.487691 0.573764 +vt 0.563274 0.690927 +vt 0.735343 0.574985 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.743883 0.446331 +vt 0.779872 0.385852 +vt 0.817351 0.446331 +vt 0.853830 0.385852 +vt 0.890820 0.446331 +vt 0.122341 0.504785 +vt 0.003867 0.504785 +vt 0.122341 0.378413 +vt 0.003867 0.378413 +s off +f 1/1 3/2 4/3 +f 2/4 1/1 4/3 +f 2/5 4/6 5/7 +f 5/7 6/8 2/5 +f 9/9 3/10 10/11 +f 3/10 1/12 10/11 +f 8/13 7/14 13/15 +f 13/15 14/16 8/13 +f 15/17 11/18 16/19 +f 12/20 16/19 11/18 +f 2/21 6/22 1/23 +f 10/24 1/23 6/22 +f 4/21 3/23 5/22 +f 9/24 5/22 3/23 +f 17/25 19/26 20/27 +f 18/28 17/25 20/27 +f 21/26 23/25 24/28 +f 22/27 21/26 24/28 +f 26/29 27/30 25/31 +f 27/30 28/32 25/31 +f 28/32 29/33 25/31 +f 31/34 32/35 30/36 +f 32/35 33/37 30/36 +f 33/37 34/38 30/36 +f 36/38 37/37 35/36 +f 37/37 38/35 35/36 +f 38/35 39/34 35/36 +f 41/33 42/32 40/31 +f 42/32 43/30 40/31 +f 43/30 44/29 40/31 +f 5/39 7/40 6/41 +f 7/40 8/42 6/41 +f 46/29 47/30 45/31 +f 47/30 48/32 45/31 +f 48/32 49/33 45/31 +f 51/33 52/32 50/31 +f 52/32 53/30 50/31 +f 53/30 54/29 50/31 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Trailer.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Trailer.obj new file mode 100644 index 0000000..bc18133 --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Truck_Trailer.obj @@ -0,0 +1,106 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v -0.800000 2.900000 -0.700000 +v 0.800000 2.900000 -0.700000 +v -0.800000 1.200000 -0.700000 +v 0.800000 1.200000 -0.700000 +v -0.800000 2.900000 -0.300000 +v 0.800000 2.900000 -0.300000 +v -0.800000 1.200000 -0.300000 +v 0.800000 1.200000 -0.300000 +v 0.800000 1.200000 -0.300000 +v 0.800000 2.900000 -0.300000 +v 0.800000 1.200000 -0.700000 +v 0.800000 2.900000 -0.700000 +v -0.800000 1.200000 -0.700000 +v -0.800000 2.900000 -0.700000 +v -0.800000 1.200000 -0.300000 +v -0.800000 2.900000 -0.300000 +v 0.780000 2.400000 -0.300000 +v 0.780000 2.700000 -0.300000 +v 0.780000 2.600000 0.000000 +v 0.780000 2.200000 0.000000 +v 0.780000 2.100000 -0.300000 +v -0.780000 2.400000 -0.300000 +v -0.780000 2.100000 -0.300000 +v -0.780000 2.200000 0.000000 +v -0.780000 2.600000 0.000000 +v -0.780000 2.700000 -0.300000 +v 0.780000 1.700000 -0.300000 +v 0.780000 2.000000 -0.300000 +v 0.780000 1.900000 0.000000 +v 0.780000 1.500000 0.000000 +v 0.780000 1.400000 -0.300000 +v -0.780000 1.700000 -0.300000 +v -0.780000 1.400000 -0.300000 +v -0.780000 1.500000 0.000000 +v -0.780000 1.900000 0.000000 +v -0.780000 2.000000 -0.300000 +v 0.800000 -0.600000 -2.000000 +v 0.800000 2.900000 -2.000000 +v -0.800000 -0.600000 -2.000000 +v -0.800000 2.900000 -2.000000 +v 0.800000 -0.600000 -0.800000 +v 0.800000 2.900000 -0.800000 +v -0.800000 -0.600000 -0.800000 +v -0.800000 2.900000 -0.800000 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.880027 0.325855 +vt 0.591008 0.325855 +vt 0.880027 0.000323 +vt 0.589446 0.324644 +vt 0.001453 0.324644 +vt 0.589446 0.001209 +vt 0.584620 0.002788 +vt 0.584620 0.324497 +vt 0.001010 0.324497 +vt 0.001010 0.002788 +vt 0.591008 0.000323 +vt 0.001453 0.001209 +s off +f 2/1 1/2 5/3 +f 5/3 6/4 2/1 +f 7/5 3/6 8/7 +f 4/8 8/7 3/6 +f 9/9 11/10 12/11 +f 10/12 9/9 12/11 +f 13/10 15/9 16/12 +f 14/11 13/10 16/12 +f 18/13 19/14 17/15 +f 19/14 20/16 17/15 +f 20/16 21/17 17/15 +f 23/17 24/16 22/15 +f 24/16 25/14 22/15 +f 25/14 26/13 22/15 +f 39/18 37/19 43/20 +f 37/21 38/22 41/23 +f 28/13 29/14 27/15 +f 29/14 30/16 27/15 +f 30/16 31/17 27/15 +f 33/17 34/16 32/15 +f 34/16 35/14 32/15 +f 35/14 36/13 32/15 +f 37/24 39/25 40/26 +f 38/27 37/24 40/26 +f 37/19 41/28 43/20 +f 40/18 44/20 42/28 +f 39/21 43/23 44/29 +f 38/22 42/29 41/23 +f 38/19 40/18 42/28 +f 40/22 39/21 44/29 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_Ute.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Ute.obj new file mode 100644 index 0000000..1d3e8bb --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Ute.obj @@ -0,0 +1,127 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v 0.600000 -0.200000 -1.100000 +v 0.600000 0.200000 -1.100000 +v -0.600000 -0.200000 -1.100000 +v -0.600000 0.200000 -1.100000 +v -0.800000 0.300000 -0.700000 +v 0.800000 0.300000 -0.700000 +v -0.800000 2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -1.000000 -0.700000 +v 0.800000 -1.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v 0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v -0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v 0.800000 -2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.300000 +v -0.800000 2.000000 -0.300000 +v 0.780000 1.200000 -0.300000 +v 0.780000 1.500000 -0.300000 +v 0.780000 1.400000 0.000000 +v 0.780000 1.000000 0.000000 +v 0.780000 0.900000 -0.300000 +v 0.780000 -1.100000 -0.300000 +v 0.780000 -0.800000 -0.300000 +v 0.780000 -0.900000 0.000000 +v 0.780000 -1.300000 0.000000 +v 0.780000 -1.400000 -0.300000 +v -0.780000 -1.100000 -0.300000 +v -0.780000 -1.400000 -0.300000 +v -0.780000 -1.300000 0.000000 +v -0.780000 -0.900000 0.000000 +v -0.780000 -0.800000 -0.300000 +v -0.780000 1.200000 -0.300000 +v -0.780000 0.900000 -0.300000 +v -0.780000 1.000000 0.000000 +v -0.780000 1.400000 0.000000 +v -0.780000 1.500000 -0.300000 +vt 0.564792 0.689981 +vt 0.564792 0.953949 +vt 0.338554 0.953949 +vt 0.338554 0.689981 +vt 0.334296 0.692438 +vt 0.334296 0.954445 +vt 0.203294 0.986197 +vt 0.203294 0.656186 +vt 0.695616 0.984433 +vt 0.572654 0.959219 +vt 0.695616 0.657719 +vt 0.572795 0.683358 +vt 0.941945 0.999442 +vt 0.694306 0.999442 +vt 0.941945 0.647349 +vt 0.694306 0.647349 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.471796 0.690927 +vt 0.487691 0.573764 +vt 0.563274 0.690927 +vt 0.735343 0.574985 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.743883 0.446331 +vt 0.779872 0.385852 +vt 0.817351 0.446331 +vt 0.853830 0.385852 +vt 0.890820 0.446331 +vt 0.122341 0.504785 +vt 0.003867 0.504785 +vt 0.122341 0.378413 +vt 0.003867 0.378413 +s off +f 1/1 3/2 4/3 +f 2/4 1/1 4/3 +f 2/5 4/6 5/7 +f 5/7 6/8 2/5 +f 9/9 3/10 10/11 +f 3/10 1/12 10/11 +f 11/13 9/14 12/15 +f 10/16 12/15 9/14 +f 8/17 7/18 13/19 +f 13/19 14/20 8/17 +f 15/21 11/22 16/23 +f 12/24 16/23 11/22 +f 2/25 6/26 1/27 +f 10/28 1/27 6/26 +f 4/25 3/27 5/26 +f 9/28 5/26 3/27 +f 17/29 19/30 20/31 +f 18/32 17/29 20/31 +f 21/30 23/29 24/32 +f 22/31 21/30 24/32 +f 26/33 27/34 25/35 +f 27/34 28/36 25/35 +f 28/36 29/37 25/35 +f 31/38 32/39 30/40 +f 32/39 33/41 30/40 +f 33/41 34/42 30/40 +f 36/42 37/41 35/40 +f 37/41 38/39 35/40 +f 38/39 39/38 35/40 +f 41/37 42/36 40/35 +f 42/36 43/34 40/35 +f 43/34 44/33 40/35 +f 5/43 7/44 6/45 +f 7/44 8/46 6/45 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarCrime_Wagon.obj b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Wagon.obj new file mode 100644 index 0000000..d6774d9 --- /dev/null +++ b/CarCrimeCity/Part2/assets/vehicles/CarCrime_Wagon.obj @@ -0,0 +1,121 @@ +# Blender v2.69 (sub 0) OBJ File: 'Car002.blend' +# www.blender.org +v 0.600000 -0.200000 -1.100000 +v 0.600000 1.600000 -1.100000 +v -0.600000 -0.200000 -1.100000 +v -0.600000 1.600000 -1.100000 +v -0.800000 2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -1.000000 -0.700000 +v 0.800000 -1.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v 0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v -0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 -2.000000 -0.300000 +v 0.800000 2.000000 -0.300000 +v 0.800000 -2.000000 -0.700000 +v 0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.700000 +v -0.800000 2.000000 -0.700000 +v -0.800000 -2.000000 -0.300000 +v -0.800000 2.000000 -0.300000 +v 0.780000 1.200000 -0.300000 +v 0.780000 1.500000 -0.300000 +v 0.780000 1.400000 0.000000 +v 0.780000 1.000000 0.000000 +v 0.780000 0.900000 -0.300000 +v 0.780000 -1.100000 -0.300000 +v 0.780000 -0.800000 -0.300000 +v 0.780000 -0.900000 0.000000 +v 0.780000 -1.300000 0.000000 +v 0.780000 -1.400000 -0.300000 +v -0.780000 -1.100000 -0.300000 +v -0.780000 -1.400000 -0.300000 +v -0.780000 -1.300000 0.000000 +v -0.780000 -0.900000 0.000000 +v -0.780000 -0.800000 -0.300000 +v -0.780000 1.200000 -0.300000 +v -0.780000 0.900000 -0.300000 +v -0.780000 1.000000 0.000000 +v -0.780000 1.400000 0.000000 +v -0.780000 1.500000 -0.300000 +vt 0.564792 0.689981 +vt 0.564792 0.953949 +vt 0.338554 0.953949 +vt 0.338554 0.689981 +vt 0.334296 0.692438 +vt 0.334296 0.954445 +vt 0.203294 0.986197 +vt 0.203294 0.656186 +vt 0.695616 0.984433 +vt 0.572654 0.959219 +vt 0.695616 0.657719 +vt 0.572795 0.683358 +vt 0.941945 0.999442 +vt 0.694306 0.999442 +vt 0.941945 0.647349 +vt 0.694306 0.647349 +vt 0.070499 0.643570 +vt 0.070499 0.998147 +vt 0.003817 0.998147 +vt 0.003817 0.643570 +vt 0.997239 0.998410 +vt 0.940308 0.998410 +vt 0.997239 0.647262 +vt 0.940308 0.647262 +vt 0.331416 0.690927 +vt 0.238667 0.577426 +vt 0.563274 0.690927 +vt 0.735343 0.574985 +vt 0.970266 0.522520 +vt 0.962942 0.572543 +vt 0.072079 0.572543 +vt 0.079403 0.522520 +vt 0.744362 0.446044 +vt 0.780351 0.385565 +vt 0.817830 0.446044 +vt 0.854309 0.385565 +vt 0.891299 0.446044 +vt 0.743883 0.446331 +vt 0.779872 0.385852 +vt 0.817351 0.446331 +vt 0.853830 0.385852 +vt 0.890820 0.446331 +s off +f 1/1 3/2 4/3 +f 2/4 1/1 4/3 +f 2/5 4/6 5/7 +f 5/7 6/8 2/5 +f 9/9 3/10 10/11 +f 3/10 1/12 10/11 +f 11/13 9/14 12/15 +f 10/16 12/15 9/14 +f 8/17 7/18 13/19 +f 13/19 14/20 8/17 +f 15/21 11/22 16/23 +f 12/24 16/23 11/22 +f 2/25 6/26 1/27 +f 10/28 1/27 6/26 +f 4/25 3/27 5/26 +f 9/28 5/26 3/27 +f 17/29 19/30 20/31 +f 18/32 17/29 20/31 +f 21/30 23/29 24/32 +f 22/31 21/30 24/32 +f 26/33 27/34 25/35 +f 27/34 28/36 25/35 +f 28/36 29/37 25/35 +f 31/38 32/39 30/40 +f 32/39 33/41 30/40 +f 33/41 34/42 30/40 +f 36/42 37/41 35/40 +f 37/41 38/39 35/40 +f 38/39 39/38 35/40 +f 41/37 42/36 40/35 +f 42/36 43/34 40/35 +f 43/34 44/33 40/35 diff --git a/CarCrimeCity/Part2/assets/vehicles/CarTex_256.png b/CarCrimeCity/Part2/assets/vehicles/CarTex_256.png new file mode 100644 index 0000000..049eb5c Binary files /dev/null and b/CarCrimeCity/Part2/assets/vehicles/CarTex_256.png differ diff --git a/CarCrimeCity/Part2/cAutomata.cpp b/CarCrimeCity/Part2/cAutomata.cpp new file mode 100644 index 0000000..f1bb2a9 --- /dev/null +++ b/CarCrimeCity/Part2/cAutomata.cpp @@ -0,0 +1,206 @@ +#include "cAutomata.h" + + +cAuto_Node::cAuto_Node() +{ + pos = { 0,0 }; +} + +cAuto_Node::cAuto_Node(const olc::vf2d &worldpos) +{ + pos = worldpos; +} + +olc::vf2d cAuto_Track::GetPostion(float t, cAuto_Node *pStart) +{ + // pStart indicates the node the automata first encounted this track + if (node[0] == pStart) + { + return node[0]->pos + (node[1]->pos - node[0]->pos) * (t / fTrackLength); + } + else + { + return node[1]->pos + (node[0]->pos - node[1]->pos) * (t / fTrackLength); + } +} + + + +cAuto_Body::cAuto_Body() +{ +} + + +cAuto_Body::~cAuto_Body() +{ +} + + +void cAuto_Body::UpdateAuto(float fElapsedTime) +{ + // Work out which node is the target destination + cAuto_Node *pExitNode = pCurrentTrack->node[0]; + if (pExitNode == pTrackOriginNode) + pExitNode = pCurrentTrack->node[1]; + + bool bAutomataCanMove = true; + + float fDistanceToAutoInFront = 1.0f; + + // First check if the vehicle overlaps with the one in front of it + + // Get an iterator for this automata + auto itThisAutomata = std::find(pCurrentTrack->listAutos.begin(), pCurrentTrack->listAutos.end(), this); + + // If this automata is at the front of this track segment + if (*itThisAutomata == pCurrentTrack->listAutos.front()) + { + // Then check all the following track segments. Take the position of + // each vehicle at the back of the track segments auto list + for (auto &track : pExitNode->listTracks) + { + if (track != pCurrentTrack && !track->listAutos.empty()) + { + // Get Auto at back + float fDistanceFromTrackStartToAutoRear = track->listAutos.back()->fAutoPos - track->listAutos.back()->fAutoLength; + + if ((*itThisAutomata)->fAutoPos < (pCurrentTrack->fTrackLength + fDistanceFromTrackStartToAutoRear - fAutoLength)) + { + // Move Automata along track, as there is space + //bAutomataCanMove = true; + fDistanceToAutoInFront = (pCurrentTrack->fTrackLength + fDistanceFromTrackStartToAutoRear - 0.1f) - (*itThisAutomata)->fAutoPos; + } + else + { + // No space, so do not move automata + bAutomataCanMove = false; + } + } + else + { + // Track in front was empty, node is clear to pass through so + //bAutomataCanMove = true; + } + } + + + + } + else + { + // Get the automata in front + auto itAutomataInFront = itThisAutomata; + itAutomataInFront--; + + // If the distance between the front of the automata in front and the fornt of this automata + // is greater than the length of the automata in front, then there is space for this automata + // to enter + if (fabs((*itAutomataInFront)->fAutoPos - (*itThisAutomata)->fAutoPos) > ((*itAutomataInFront)->fAutoLength + 0.1f)) + { + // Move Automata along track + //bAutomataCanMove = true; + fDistanceToAutoInFront = ((*itAutomataInFront)->fAutoPos - (*itAutomataInFront)->fAutoLength - 0.1f) - (*itThisAutomata)->fAutoPos; + } + else + { + // No space, so do not move automata + bAutomataCanMove = false; + } + } + + if (bAutomataCanMove) + { + if (fDistanceToAutoInFront > pCurrentTrack->fTrackLength) fDistanceToAutoInFront = pCurrentTrack->fTrackLength; + fAutoPos += fElapsedTime * std::max(fDistanceToAutoInFront, 1.0f) * (fAutoLength < 0.1f ? 0.3f : 0.5f); + } + + + if (fAutoPos >= pCurrentTrack->fTrackLength) + { + // Automata has reached end of current track + + // Check if it can transition beyond node + if (!pExitNode->bBlock) + { + // It can, so reset position along track back to start + fAutoPos -= pCurrentTrack->fTrackLength; + + // Choose a track from the node not equal to this one, that has an unblocked exit node + + // For now choose at random + cAuto_Track *pNewTrack = nullptr; + + if (pExitNode->listTracks.size() == 2) + { + // Automata is travelling along straight joined sections, one of the + // tracks is the track its just come in on, the other is the exit, so + // choose the exit. + auto it = pExitNode->listTracks.begin(); + pNewTrack = (*it); + if (pCurrentTrack == pNewTrack) + { + ++it; + pNewTrack = (*it); + } + } + else + { + // Automata has reached a junction with several exits + while (pNewTrack == nullptr) + { + int i = rand() % pExitNode->listTracks.size(); + int j = 0; + for (auto it = pExitNode->listTracks.begin(); it != pExitNode->listTracks.end(); ++it) + { + cAuto_Track* track = (*it); + + // Work out which node is the target destination + cAuto_Node *pNewExitNode = track->node[0]; + if (pNewExitNode == pExitNode) + pNewExitNode = track->node[1]; + + if (j == i && track != pCurrentTrack && !pNewExitNode->bBlock /*((*it)->cell != pCurrentTrack->cell)*/) + { + pNewTrack = track; + break; + } + + j++; + } + } + } + + + // Change to new track, the origin node of the next + // track is the same as the exit node to the current track + pTrackOriginNode = pExitNode; + + // Remove the automata from the front of the queue + // on the current track + pCurrentTrack->listAutos.pop_front(); + + // Switch the automatas track link to the new track + pCurrentTrack = pNewTrack; + + // Push the automata onto the back of the new track queue + pCurrentTrack->listAutos.push_back(this); + + } + else + { + // It cant pass the node, so clamp automata at this location + fAutoPos = pCurrentTrack->fTrackLength; + } + + } + else + { + // Automata is travelling + vAutoPos = pCurrentTrack->GetPostion(fAutoPos, pTrackOriginNode); + } +} + + + + + diff --git a/CarCrimeCity/Part2/cAutomata.h b/CarCrimeCity/Part2/cAutomata.h new file mode 100644 index 0000000..84b9c14 --- /dev/null +++ b/CarCrimeCity/Part2/cAutomata.h @@ -0,0 +1,107 @@ +/* + Top Down City Based Car Crime Game - Part #2 + "Colin, I hope you're shooting 600+ wherever you are buddy. RIP." - javidx9 + + License (OLC-3) + ~~~~~~~~~~~~~~~ + + Copyright 2018-2019 OneLoneCoder.com + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions or derivations of source code must retain the above + copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions or derivative works in binary form must reproduce + the above copyright notice. This list of conditions and the following + disclaimer must be reproduced in the documentation and/or other + materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Instructions: + ~~~~~~~~~~~~~ + Scroll with middle mouse wheel, TAB toggle edit mode, R to place road + P to place pavement, Q to place building, Arrow keys to drive car + + Relevant Video: https://youtu.be/fIV6P1W-wuo + + Links + ~~~~~ + YouTube: https://www.youtube.com/javidx9 + https://www.youtube.com/javidx9extra + Discord: https://discord.gg/WhwHUMV + Twitter: https://www.twitter.com/javidx9 + Twitch: https://www.twitch.tv/javidx9 + GitHub: https://www.github.com/onelonecoder + Patreon: https://www.patreon.com/javidx9 + Homepage: https://www.onelonecoder.com + + Author + ~~~~~~ + David Barr, aka javidx9, ©OneLoneCoder 2019 +*/ + + +#pragma once + +#include "olcPixelGameEngine.h" + +class cAuto_Track; +class cAuto_Node; +class cAuto_Body; +class cCell; + +class cAuto_Node +{ +public: + cAuto_Node(); + cAuto_Node(const olc::vf2d &worldpos); + olc::vf2d pos; + bool bBlock = false; + std::list listTracks; +}; + +class cAuto_Track +{ +public: + cAuto_Node* node[2]; // Two end nodes + cCell* cell; // Pointer to host cell + olc::vf2d GetPostion(float t, cAuto_Node *pstart); + std::list listAutos; + float fTrackLength = 1.0f; +}; + +class cAuto_Body +{ +public: + cAuto_Body(); + ~cAuto_Body(); + +public: + void UpdateAuto(float fElapsedTime); + +public: + olc::vf2d vAutoPos = { 0.0f, 0.0f }; + float fAutoPos = 0.0f; // Location of automata along track + float fAutoLength = 0.0f; // Physical length of automata + cAuto_Track *pCurrentTrack = nullptr; + cAuto_Node *pTrackOriginNode = nullptr; + +}; diff --git a/CarCrimeCity/Part2/cCarCrimeCity.cpp b/CarCrimeCity/Part2/cCarCrimeCity.cpp new file mode 100644 index 0000000..572b7a0 --- /dev/null +++ b/CarCrimeCity/Part2/cCarCrimeCity.cpp @@ -0,0 +1,709 @@ +#include "cCarCrimeCity.h" + +cCarCrimeCity::cCarCrimeCity() +{ + sAppName = "Car Crime City"; +} + +cCarCrimeCity::~cCarCrimeCity() +{ +} + +bool cCarCrimeCity::OnUserCreate() +{ + // Initialise PGEX 3D + olc::GFX3D::ConfigureDisplay(); + + // Load fixed system assets, i.e. those need to simply do anything + if (!LoadAssets()) return false; + + // Create Default city + pCity = new cCityMap(cGameSettings::nDefaultMapWidth, cGameSettings::nDefaultMapHeight, mapAssetTextures, mapAssetMeshes, mapAssetTransform); + + // If a city map file has been specified, then load it + if (!cGameSettings::sDefaultCityFile.empty()) + { + if (!pCity->LoadCity(cGameSettings::sDefaultCityFile)) + { + std::cout << "Failed to load '" << cGameSettings::sDefaultCityFile << "'" << std::endl; + return false; + } + } + + return true; +} + +bool cCarCrimeCity::LoadAssets() +{ + // Game Settings should have loaded all the relevant file information + // to start loading asset information. Game assets will be stored in + // a map structure. Maps can have slightly longer access times, so each + // in game object will have facility to extract required resources once + // when it is created, meaning no map search during normal use + + // System Meshes + // A simple flat unit quad + olc::GFX3D::mesh* meshQuad = new olc::GFX3D::mesh(); + meshQuad->tris = + { + { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + }; + mapAssetMeshes["UnitQuad"] = meshQuad; + + //// The four outer walls of a cell + olc::GFX3D::mesh* meshWallsOut = new olc::GFX3D::mesh(); + meshWallsOut->tris = + { + // EAST + { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.2f, 1.0f, 1.0f, 0.0f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + + // WEST + { 0.0f, 0.0f, 0.2f, 1.0f, 0.0f, 1.0f, 0.2f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + { 0.0f, 0.0f, 0.2f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + + // TOP + { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.2f, 1.0f, 1.0f, 1.0f, 0.2f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + { 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.2f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + + // BOTTOM + { 1.0f, 0.0f, 0.2f, 1.0f, 0.0f, 0.0f, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + { 1.0f, 0.0f, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::WHITE, olc::WHITE, olc::WHITE }, + }; + mapAssetMeshes["WallsOut"] = meshWallsOut; + + + // System Textures + for (auto &asset : cGameSettings::vecAssetTextures) + { + olc::Sprite *sprAsset = new olc::Sprite(); + if (sprAsset->LoadFromFile(asset.sFile)) + { + mapAssetTextures[asset.sName] = sprAsset; + } + else + { + std::cout << "Failed to load " << asset.sName << std::endl; + return false; + } + } + + // Break up roads sprite into individual sprites. Why? Its easier to maintain + // the roads sprite as a single image, but easier to use if they are all individual. + // Breaking it up manually in the image editing software is time consuming so just + // do it here + int nRoadTexSize = 256; // In pixels in base texture + int nRoadTexOffset = 64; // There exists a 64 pixel offset from top left of source image + for (int r = 0; r < 12; r++) + { + olc::Sprite* road = new olc::Sprite(nRoadTexSize, nRoadTexSize); + SetDrawTarget(road); + DrawPartialSprite(0, 0, mapAssetTextures["AllRoads"], ((r % 3) * nRoadTexSize) + nRoadTexOffset, ((r / 3) * nRoadTexSize) + nRoadTexOffset, nRoadTexSize, nRoadTexSize); + switch (r) + { + case 0: mapAssetTextures["Road_V"] = road; break; + case 1: mapAssetTextures["Road_H"] = road; break; + case 2: mapAssetTextures["Pavement"] = road; break; + case 3: mapAssetTextures["Road_C1"] = road; break; + case 4: mapAssetTextures["Road_T1"] = road; break; + case 5: mapAssetTextures["Road_C2"] = road; break; + case 6: mapAssetTextures["Road_T2"] = road; break; + case 7: mapAssetTextures["Road_X"] = road; break; + case 8: mapAssetTextures["Road_T3"] = road; break; + case 9: mapAssetTextures["Road_C3"] = road; break; + case 10: mapAssetTextures["Road_T4"] = road; break; + case 11: mapAssetTextures["Road_C4"] = road; break; + } + } + SetDrawTarget(nullptr); + + + // Load Buildings + for (auto &asset : cGameSettings::vecAssetBuildings) + { + mapAssetMeshes[asset.sDescription] = new olc::GFX3D::mesh(); + mapAssetMeshes[asset.sDescription]->LoadOBJFile(asset.sModelOBJ); + mapAssetTextures[asset.sDescription] = new olc::Sprite(asset.sModelPNG); + + olc::GFX3D::mat4x4 matScale = olc::GFX3D::Math::Mat_MakeScale(asset.fScale[0], asset.fScale[1], asset.fScale[2]); + olc::GFX3D::mat4x4 matTranslate = olc::GFX3D::Math::Mat_MakeTranslation(asset.fTranslate[0], asset.fTranslate[1], asset.fTranslate[2]); + olc::GFX3D::mat4x4 matRotateX = olc::GFX3D::Math::Mat_MakeRotationX(asset.fRotate[0]); + olc::GFX3D::mat4x4 matRotateY = olc::GFX3D::Math::Mat_MakeRotationY(asset.fRotate[1]); + olc::GFX3D::mat4x4 matRotateZ = olc::GFX3D::Math::Mat_MakeRotationZ(asset.fRotate[2]); + olc::GFX3D::mat4x4 matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTranslate, matScale); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateX); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateY); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateZ); + mapAssetTransform[asset.sDescription] = matTransform; + } + + // Load Vehicles + for (auto &asset : cGameSettings::vecAssetVehicles) + { + mapAssetMeshes[asset.sDescription] = new olc::GFX3D::mesh(); + mapAssetMeshes[asset.sDescription]->LoadOBJFile(asset.sModelOBJ); + mapAssetTextures[asset.sDescription] = new olc::Sprite(asset.sModelPNG); + + olc::GFX3D::mat4x4 matScale = olc::GFX3D::Math::Mat_MakeScale(asset.fScale[0], asset.fScale[1], asset.fScale[2]); + olc::GFX3D::mat4x4 matTranslate = olc::GFX3D::Math::Mat_MakeTranslation(asset.fTranslate[0], asset.fTranslate[1], asset.fTranslate[2]); + olc::GFX3D::mat4x4 matRotateX = olc::GFX3D::Math::Mat_MakeRotationX(asset.fRotate[0]); + olc::GFX3D::mat4x4 matRotateY = olc::GFX3D::Math::Mat_MakeRotationY(asset.fRotate[1]); + olc::GFX3D::mat4x4 matRotateZ = olc::GFX3D::Math::Mat_MakeRotationZ(asset.fRotate[2]); + olc::GFX3D::mat4x4 matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTranslate, matScale); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateX); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateY); + matTransform = olc::GFX3D::Math::Mat_MultiplyMatrix(matTransform, matRotateZ); + mapAssetTransform[asset.sDescription] = matTransform; + } + + return true; +} + +void cCarCrimeCity::SpawnPedestrian(int x, int y) +{ + cCell* cell = pCity->Cell(x, y); + + cAuto_Track *t = ((cCell_Road*)cell)->pSafePedestrianTrack; + if (t == nullptr) return; + + cAuto_Body *a = new cAuto_Body(); + a->fAutoLength = 0.05f; + a->pCurrentTrack = t; + a->pCurrentTrack->listAutos.push_back(a); + a->pTrackOriginNode = t->node[0]; + a->UpdateAuto(0.0f); + listAutomata.push_back(a); +} + +void cCarCrimeCity::SpawnVehicle(int x, int y) +{ + cCell* cell = pCity->Cell(x, y); + + cAuto_Track *t = ((cCell_Road*)cell)->pSafeCarTrack; + if (t == nullptr) return; + + cAuto_Body *a = new cAuto_Body(); + a->fAutoLength = 0.2f; + a->pCurrentTrack = t; + a->pCurrentTrack->listAutos.push_back(a); + a->pTrackOriginNode = t->node[0]; + a->UpdateAuto(0.0f); + listAutomata.push_back(a); +} + +void cCarCrimeCity::DoEditMode(float fElapsedTime) +{ + // Get cell under mouse cursor + cCell* mcell = pCity->Cell(nMouseX, nMouseY); + bool bTempCellAdded = false; + + // Left click and drag adds cells + if (mcell != nullptr && GetMouse(0).bHeld) + setSelectedCells.emplace(nMouseY * pCity->GetWidth() + nMouseX); + + // Right click clears selection + if (GetMouse(1).bReleased) + setSelectedCells.clear(); + + if (setSelectedCells.empty()) + { + // If nothing can be edited validly then just exit + if (mcell == nullptr) + return; + + // else set is empty, so temporarily add current cell to it + setSelectedCells.emplace(nMouseY * pCity->GetWidth() + nMouseX); + bTempCellAdded = true; + } + + // If the map changes, we will need to update + // the automata, and adjacency + bool bMapChanged = false; + + // Press "G" to apply grass + if (GetKey(olc::Key::G).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + cCell* cell = pCity->Replace(x, y, new cCell_Plane(pCity, x, y, PLANE_GRASS)); + cell->LinkAssets(mapAssetTextures, mapAssetMeshes, mapAssetTransform); + } + + bMapChanged = true; + } + + // Press "P" to apply Pavement + if (GetKey(olc::Key::P).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + cCell* cell = pCity->Replace(x, y, new cCell_Plane(pCity, x, y, PLANE_ASPHALT)); + cell->LinkAssets(mapAssetTextures, mapAssetMeshes, mapAssetTransform); + } + + bMapChanged = true; + } + + // Press "W" to apply Water + if (GetKey(olc::Key::W).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + cCell* cell = pCity->Replace(x, y, new cCell_Water(pCity, x, y)); + cell->LinkAssets(mapAssetTextures, mapAssetMeshes, mapAssetTransform); + } + + bMapChanged = true; + } + + // Press "R" to apply Roads + if (GetKey(olc::Key::Q).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + cCell* cell = pCity->Replace(x, y, new cCell_Building("Apartments_1", pCity, x, y)); + cell->LinkAssets(mapAssetTextures, mapAssetMeshes, mapAssetTransform); + } + + bMapChanged = true; + } + + + // Press "R" to apply Roads + if (GetKey(olc::Key::R).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + cCell* cell = pCity->Replace(x, y, new cCell_Road(pCity, x, y)); + cell->LinkAssets(mapAssetTextures, mapAssetMeshes, mapAssetTransform); + } + + bMapChanged = true; + } + + + + if (GetKey(olc::Key::C).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + SpawnVehicle(x, y); + } + } + + + if (GetKey(olc::Key::V).bPressed) + { + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + SpawnPedestrian(x, y); + } + } + + if (bMapChanged) + { + // The navigation nodes may have tracks attached to them, so get rid of them + // all. Below we will reconstruct all tracks because city has changed + pCity->RemoveAllTracks(); + + for (auto &a : listAutomata) delete a; + listAutomata.clear(); + + for (int x = 0; x < pCity->GetWidth(); x++) + { + for (int y = 0; y < pCity->GetHeight(); y++) + { + cCell *c = pCity->Cell(x, y); + + // Update adjacency information, i.e. those cells whose + // state changes based on neighbouring cells + c->CalculateAdjacency(); + } + } + } + + + // To facilitate "edit under cursor" we added a temporary cell + // which needs to be removed now + if (bTempCellAdded) + setSelectedCells.clear(); +} + +olc::vf2d cCarCrimeCity::GetMouseOnGround(const olc::vf2d &vMouseScreen) +{ + olc::GFX3D::vec3d vLookTarget = olc::GFX3D::Math::Vec_Add(vEye, vLookDir); + olc::GFX3D::mat4x4 matProj = olc::GFX3D::Math::Mat_MakeProjection(90.0f, (float)ScreenHeight() / (float)ScreenWidth(), 0.1f, 1000.0f); + olc::GFX3D::mat4x4 matView = olc::GFX3D::Math::Mat_PointAt(vEye, vLookTarget, vUp); + olc::GFX3D::vec3d vecMouseDir = { + 2.0f * ((vMouseScreen.x / (float)ScreenWidth()) - 0.5f) / matProj.m[0][0], + 2.0f * ((vMouseScreen.y / (float)ScreenHeight()) - 0.5f) / matProj.m[1][1], + 1.0f, + 0.0f }; + + olc::GFX3D::vec3d vecMouseOrigin = { 0.0f, 0.0f, 0.0f }; + vecMouseOrigin = olc::GFX3D::Math::Mat_MultiplyVector(matView, vecMouseOrigin); + vecMouseDir = olc::GFX3D::Math::Mat_MultiplyVector(matView, vecMouseDir); + vecMouseDir = olc::GFX3D::Math::Vec_Mul(vecMouseDir, 1000.0f); + vecMouseDir = olc::GFX3D::Math::Vec_Add(vecMouseOrigin, vecMouseDir); + + // Perform line/plane intersection to determine mouse position in world space + olc::GFX3D::vec3d plane_p = { 0.0f, 0.0f, 0.0f }; + olc::GFX3D::vec3d plane_n = { 0.0f, 0.0f, 1.0f }; + float t = 0.0f; + olc::GFX3D::vec3d mouse3d = olc::GFX3D::Math::Vec_IntersectPlane(plane_p, plane_n, vecMouseOrigin, vecMouseDir, t); + return { mouse3d.x, mouse3d.y }; +} + +bool cCarCrimeCity::OnUserUpdate(float fElapsedTime) +{ + fGlobalTime += fElapsedTime; + + if (GetKey(olc::Key::TAB).bReleased) bEditMode = !bEditMode; + + if (bEditMode) // Use mouse to pan and zoom, and place objects + { + vEye = vCamera; + olc::vf2d vMouseScreen = { (float)GetMouseX(), (float)GetMouseY() }; + olc::vf2d vMouseOnGroundBeforeZoom = GetMouseOnGround(vMouseScreen); + + vOffset = { 0,0 }; + + if (IsFocused()) + { + if (GetMouse(2).bPressed) { vStartPan = vMouseOnGroundBeforeZoom; } + if (GetMouse(2).bHeld) { vOffset = (vStartPan - vMouseOnGroundBeforeZoom); }; + + if (GetMouseWheel() > 0) + { + vCamera.z *= 0.5f; + } + + if (GetMouseWheel() < 0) + { + vCamera.z *= 1.5f; + } + } + + vEye = vCamera; + olc::vf2d vMouseOnGroundAfterZoom = GetMouseOnGround(vMouseScreen); + vOffset += (vMouseOnGroundBeforeZoom - vMouseOnGroundAfterZoom); + vCamera.x += vOffset.x; + vCamera.y += vOffset.y; + vEye = vCamera; + + // Get Integer versions of mouse coords in world space + nMouseX = (int)vMouseOnGroundAfterZoom.x; + nMouseY = (int)vMouseOnGroundAfterZoom.y; + + DoEditMode(fElapsedTime); + } + else + { + // Not in edit mode, so camera follows player + if (GetKey(olc::Key::LEFT).bHeld) fAngle += -2.5f * fElapsedTime; + if (GetKey(olc::Key::RIGHT).bHeld) fAngle += 2.5f * fElapsedTime; + if (GetKey(olc::Key::UP).bHeld) + { + carvel = { cos(fAngle), sin(fAngle) }; + carpos += carvel * 2.0f * fElapsedTime; + } + + vCamera.x = carpos.x; + vCamera.y = carpos.y; + vEye = vCamera; + } + + /*fAngle = 0.0f; + if (GetKey(olc::Key::LEFT).bHeld) fAngle = -0.8f; + if (GetKey(olc::Key::RIGHT).bHeld) fAngle = 0.8f;*/ + + + //car.UpdateDrive(fElapsedTime, 1.0f, GetKey(olc::Key::UP).bHeld, GetKey(olc::Key::SPACE).bHeld, GetKey(olc::Key::DOWN).bHeld, fAngle); + + + //if (car.bSkidding && fmod(fGlobalTime, 0.05f) < 0.01f) + //{ + // listDecalSmoke.push_front({ 0.1f, {car.vPosRear.x, car.vPosRear.y, -0.03f} }); + //} + + + //// Update Decals + //for (auto &d : listDecalSmoke) + //{ + // d.fLifetime += fElapsedTime; + //} + + //listDecalSmoke.remove_if([](const sSmokeDecal &d) {return d.fLifetime > 2.0f; }); + + //if (!bEditMode) + //{ + // vCamera.x = car.GetOrigin().x; + // vCamera.y = car.GetOrigin().y; + //} + + + //float fTargetHeight = -1.0f; + //int nCarX = vCamera.x; + //int nCarY = vCamera.y; + + std::vector vecNeighbours; + + //// Check surrounding cells height + //for (int x = nCarX - 1; x < nCarX + 2; x++) + // for (int y = nCarY - 1; y < nCarY + 2; y++) + // { + // if (pCity->Cell(x,y) && pCity->Cell(x, y)->bBuilding) + // { + // cGameObjectQuad ob(1.0f, 1.0f); + // ob.pos = { (float)x + 0.5f, (float)y + 0.5f, 0.0f, 1.0f }; + // ob.TransformModelToWorld(); + // vecNeighbours.push_back(ob); + // fTargetHeight = -2.0f; + // } + // } + + //goCar->pos.x = car.GetOrigin().x; + //goCar->pos.y = car.GetOrigin().y; + //goCar->fAngle = car.GetRotation(); + //goCar->TransformModelToWorld(); + + //for (auto &ob : vecNeighbours) + //{ + // if (goCar->StaticCollisionWith(ob, true)) + // { + // goCar->TransformModelToWorld(); + // car.vPosRear.x += goCar->pos.x - car.GetOrigin().x; + // car.vPosRear.y += goCar->pos.y - car.GetOrigin().y; + // car.vPosFront.x += goCar->pos.x - car.GetOrigin().x; + // car.vPosFront.y += goCar->pos.y - car.GetOrigin().y; + // car.fSpeed = 0.0f; + // } + //} + + //if(!bEditMode) + // vCamera.z += (fTargetHeight - vCamera.z) * 10.0f * fElapsedTime; + + + //car.UpdateTow(fElapsedTime, { mouse3d.x, mouse3d.y }); + + + + //for (int v = 1; vGetWidth(), (int)viewWorldBottomRight.x + 1); + int nStartY = std::max(0, (int)viewWorldTopLeft.y - 1); + int nEndY = std::min(pCity->GetHeight(), (int)viewWorldBottomRight.y + 1); + + // Only update automata for cells near player + int nAutomStartX = std::max(0, (int)viewWorldTopLeft.x - 3); + int nAutomEndX = std::min(pCity->GetWidth(), (int)viewWorldBottomRight.x + 3); + int nAutomStartY = std::max(0, (int)viewWorldTopLeft.y - 3); + int nAutomEndY = std::min(pCity->GetHeight(), (int)viewWorldBottomRight.y + 3); + + int nLocalStartX = std::max(0, (int)vCamera.x - 3); + int nLocalEndX = std::min(pCity->GetWidth(), (int)vCamera.x + 3); + int nLocalStartY = std::max(0, (int)vCamera.y - 3); + int nLocalEndY = std::min(pCity->GetHeight(), (int)vCamera.y + 3); + + + // Update Cells + for (int x = nStartX; x < nEndX; x++) + { + for (int y = nStartY; y < nEndY; y++) + { + pCity->Cell(x, y)->Update(fElapsedTime); + } + } + + // Update Automata + for (auto &a : listAutomata) + { + a->UpdateAuto(fElapsedTime); + + // If automata is too far from camera, remove it + if ((a->vAutoPos - olc::vf2d(vCamera.x, vCamera.y)).mag() > 5.0f) + { + // Despawn automata + + // 1) Disconnect it from track + a->pCurrentTrack->listAutos.remove(a); + + // 2) Erase it from memory + delete a; a = nullptr; + } + } + + // Remove dead automata, their pointer has been set to nullptr in the list + listAutomata.remove(nullptr); + + // Maintain a certain level of automata in vicinty of player + if (listAutomata.size() < 20) + { + bool bSpawnOK = false; + int nSpawnAttempt = 20; + while (!bSpawnOK && nSpawnAttempt > 0) + { + // Find random cell on edge of vicinty, which is out of view of the player + float fRandomAngle = ((float)rand() / (float)RAND_MAX) * 2.0f * 3.14159f; + int nRandomCellX = vCamera.x + cos(fRandomAngle) * 3.0f; + int nRandomCellY = vCamera.y + sin(fRandomAngle) * 3.0f; + + nSpawnAttempt--; + + if (pCity->Cell(nRandomCellX, nRandomCellY) && pCity->Cell(nRandomCellX, nRandomCellY)->nCellType == CELL_ROAD) + { + bSpawnOK = true; + + // Add random automata + if (rand() % 100 < 50) + { + // Spawn Pedestrian + SpawnPedestrian(nRandomCellX, nRandomCellY); + } + else + { + // Spawn Vehicle + SpawnVehicle(nRandomCellX, nRandomCellY); + // TODO: Get % chance of vehicle spawn from lua script + } + } + } + } + + + + + // Render Scene + Clear(olc::BLUE); + olc::GFX3D::ClearDepth(); + + // Create rendering pipeline + olc::GFX3D::PipeLine pipe; + pipe.SetProjection(90.0f, (float)ScreenHeight() / (float)ScreenWidth(), 0.1f, 1000.0f, 0.0f, 0.0f, (float)ScreenWidth(), (float)ScreenHeight()); + olc::GFX3D::vec3d vLookTarget = olc::GFX3D::Math::Vec_Add(vEye, vLookDir); + pipe.SetCamera(vEye, vLookTarget, vUp); + + + // Add global illumination vector (sunlight) + olc::GFX3D::vec3d lightdir = { 1.0f, 1.0f, -1.0f }; + pipe.SetLightSource(0, olc::GFX3D::LIGHT_AMBIENT, olc::Pixel(100,100,100), { 0,0,0 }, lightdir); + pipe.SetLightSource(1, olc::GFX3D::LIGHT_DIRECTIONAL, olc::WHITE, { 0,0,0 }, lightdir); + + + // RENDER CELL CONTENTS + + // Render Base Objects (those without alpha components) + for (int x = nStartX; x < nEndX; x++) + { + //omp_set_dynamic(0); + //omp_set_num_threads(4); + //#pragma omp parallel for + for (int y = nStartY; y < nEndY; y++) + { + pCity->Cell(x, y)->DrawBase(this, pipe); + } + //#pragma omp barrier + } + + // Render Upper Objects (those with alpha components) + for (int x = nStartX; x < nEndX; x++) + { + for (int y = nStartY; y < nEndY; y++) + { + pCity->Cell(x, y)->DrawAlpha(this, pipe); + } + } + + if (bEditMode) + { + // Render additional per cell debug information + for (int x = nStartX; x < nEndX; x++) + { + for (int y = nStartY; y < nEndY; y++) + { + pCity->Cell(x, y)->DrawDebug(this, pipe); + } + } + } + + if (bEditMode) + { + // Draw Selections + for (auto &c : setSelectedCells) + { + int x = c % pCity->GetWidth(); + int y = c / pCity->GetWidth(); + olc::GFX3D::mat4x4 matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)x, (float)y, 0.01f); + pipe.SetTransform(matWorld); + pipe.Render(mapAssetMeshes["UnitQuad"]->tris, olc::GFX3D::RENDER_WIRE); + } + } + + // RENDER AUTOMATA + + std::string test[] = { "Sedan", "SUV", "TruckCab", "TruckTrailer", "UTE", "Wagon" }; + int i = 0; + for (auto &a : listAutomata) + { + olc::GFX3D::vec3d v = { a->vAutoPos.x, a->vAutoPos.y, 0.0f }; + + /*olc::GFX3D::mat4x4 matWorld = olc::GFX3D::Math::Mat_MakeTranslation(a->vAutoPos.x, a->vAutoPos.y, 0.01f); + matWorld = olc::GFX3D::Math::Mat_MultiplyMatrix(mapAssetTransform[test[i]], matWorld); + pipe.SetTransform(matWorld); + pipe.SetTexture(mapAssetTextures[test[i]]); + pipe.Render(mapAssetMeshes[test[i]]->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_LIGHTS); + i++; + i = i % 6;*/ + + pipe.RenderCircleXZ(v, a->fAutoLength < 0.1f ? 0.05f : 0.07f, a->fAutoLength < 0.1f ? olc::MAGENTA : olc::YELLOW); + } + + + // Draw Player Vehicle + { + olc::GFX3D::mat4x4 matRotateZ = olc::GFX3D::Math::Mat_MakeRotationZ(fAngle); + olc::GFX3D::mat4x4 matTranslate = olc::GFX3D::Math::Mat_MakeTranslation(carpos.x, carpos.y, 0.01f); + olc::GFX3D::mat4x4 matWorld = olc::GFX3D::Math::Mat_MultiplyMatrix(mapAssetTransform["Sedan"], matRotateZ); + matWorld = olc::GFX3D::Math::Mat_MultiplyMatrix(matWorld, matTranslate); + pipe.SetTransform(matWorld); + pipe.SetTexture(mapAssetTextures["Sedan"]); + pipe.Render(mapAssetMeshes[test[i]]->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_LIGHTS); + } + + DrawString(10, 10, "Automata: " + std::to_string(listAutomata.size()), olc::WHITE); + + + if (GetKey(olc::Key::ESCAPE).bPressed) + return false; + + return true; +} + +bool cCarCrimeCity::OnUserDestroy() +{ + return true; +} diff --git a/CarCrimeCity/Part2/cCarCrimeCity.h b/CarCrimeCity/Part2/cCarCrimeCity.h new file mode 100644 index 0000000..7ff0673 --- /dev/null +++ b/CarCrimeCity/Part2/cCarCrimeCity.h @@ -0,0 +1,289 @@ +/* + Top Down City Based Car Crime Game - Part #2 + "Colin, I hope you're shooting 600+ wherever you are buddy. RIP." - javidx9 + + License (OLC-3) + ~~~~~~~~~~~~~~~ + + Copyright 2018-2019 OneLoneCoder.com + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions or derivations of source code must retain the above + copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions or derivative works in binary form must reproduce + the above copyright notice. This list of conditions and the following + disclaimer must be reproduced in the documentation and/or other + materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Instructions: + ~~~~~~~~~~~~~ + Scroll with middle mouse wheel, TAB toggle edit mode, R to place road + P to place pavement, Q to place building, Arrow keys to drive car + + Relevant Video: https://youtu.be/fIV6P1W-wuo + + Links + ~~~~~ + YouTube: https://www.youtube.com/javidx9 + https://www.youtube.com/javidx9extra + Discord: https://discord.gg/WhwHUMV + Twitter: https://www.twitter.com/javidx9 + Twitch: https://www.twitch.tv/javidx9 + GitHub: https://www.github.com/onelonecoder + Patreon: https://www.patreon.com/javidx9 + Homepage: https://www.onelonecoder.com + + Author + ~~~~~~ + David Barr, aka javidx9, ©OneLoneCoder 2019 +*/ + + +#pragma once + +#include "olcPixelGameEngine.h" +#include "olcPGEX_Graphics3D.h" + +#include "cGameSettings.h" +#include "cCityMap.h" + +#include +#include + +struct sSmokeDecal +{ + float fLifetime = 0.1f; + olc::GFX3D::vec3d pos; +}; + +class cCarCrimeCity : public olc::PixelGameEngine +{ +public: + cCarCrimeCity(); + ~cCarCrimeCity(); + +private: + bool OnUserCreate() override; + bool OnUserUpdate(float fElapsedTime) override; + bool OnUserDestroy() override; + +private: + + class cGameObjectQuad + { + public: + cGameObjectQuad(float w, float h) + { + fWidth = w; + fHeight = h; + fAngle = 0.0f; + + // Construct Model Quad Geometry + vecPointsModel = { {-fWidth / 2.0f, -fHeight / 2.0f, -0.01f, 1.0f}, + {-fWidth / 2.0f, +fHeight / 2.0f, -0.01f, 1.0f}, + {+fWidth / 2.0f, +fHeight / 2.0f, -0.01f, 1.0f}, + {+fWidth / 2.0f, -fHeight / 2.0f, -0.01f, 1.0f} }; + + vecPointsWorld.resize(vecPointsModel.size()); + TransformModelToWorld(); + } + + void TransformModelToWorld() + { + for (size_t i = 0; i < vecPointsModel.size(); ++i) + { + vecPointsWorld[i] = { + (vecPointsModel[i].x * cosf(fAngle)) - (vecPointsModel[i].y * sinf(fAngle)) + pos.x, + (vecPointsModel[i].x * sinf(fAngle)) + (vecPointsModel[i].y * cosf(fAngle)) + pos.y, + vecPointsModel[i].z, + vecPointsModel[i].w + }; + } + } + + std::vector GetTriangles() + { + // Return triangles based upon this quad + return + { + {vecPointsWorld[0], vecPointsWorld[1], vecPointsWorld[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::RED}, + {vecPointsWorld[0], vecPointsWorld[2], vecPointsWorld[3], 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, olc::RED}, + }; + } + + // Use rectangle edge intersections. + bool StaticCollisionWith(cGameObjectQuad &r2, bool bResolveStatic = false) + { + struct vec2d { float x; float y; }; + + bool bCollision = false; + + // Check diagonals of R1 against edges of R2 + for (size_t p = 0; p < vecPointsWorld.size(); p++) + { + vec2d line_r1s = { pos.x, pos.y }; + vec2d line_r1e = { vecPointsWorld[p].x, vecPointsWorld[p].y }; + + vec2d displacement = { 0,0 }; + + for (size_t q = 0; q < r2.vecPointsWorld.size(); q++) + { + vec2d line_r2s = { r2.vecPointsWorld[q].x, r2.vecPointsWorld[q].y }; + vec2d line_r2e = { r2.vecPointsWorld[(q + 1) % r2.vecPointsWorld.size()].x, r2.vecPointsWorld[(q + 1) % r2.vecPointsWorld.size()].y }; + + // Standard "off the shelf" line segment intersection + float h = (line_r2e.x - line_r2s.x) * (line_r1s.y - line_r1e.y) - (line_r1s.x - line_r1e.x) * (line_r2e.y - line_r2s.y); + float t1 = ((line_r2s.y - line_r2e.y) * (line_r1s.x - line_r2s.x) + (line_r2e.x - line_r2s.x) * (line_r1s.y - line_r2s.y)) / h; + float t2 = ((line_r1s.y - line_r1e.y) * (line_r1s.x - line_r2s.x) + (line_r1e.x - line_r1s.x) * (line_r1s.y - line_r2s.y)) / h; + + if (t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f) + { + if (bResolveStatic) + { + displacement.x += (1.0f - t1) * (line_r1e.x - line_r1s.x); + displacement.y += (1.0f - t1) * (line_r1e.y - line_r1s.y); + bCollision = true; + } + else + return true; + } + } + + pos.x -= displacement.x; + pos.y -= displacement.y; + } + + // Check diagonals of R2 against edges of R1 + for (size_t p = 0; p < r2.vecPointsWorld.size(); p++) + { + vec2d line_r1s = { r2.pos.x, r2.pos.y }; + vec2d line_r1e = { r2.vecPointsWorld[p].x, r2.vecPointsWorld[p].y }; + + vec2d displacement = { 0,0 }; + + for (size_t q = 0; q < vecPointsWorld.size(); q++) + { + vec2d line_r2s = { vecPointsWorld[q].x, vecPointsWorld[q].y }; + vec2d line_r2e = { vecPointsWorld[(q + 1) % vecPointsWorld.size()].x, vecPointsWorld[(q + 1) % vecPointsWorld.size()].y }; + + // Standard "off the shelf" line segment intersection + float h = (line_r2e.x - line_r2s.x) * (line_r1s.y - line_r1e.y) - (line_r1s.x - line_r1e.x) * (line_r2e.y - line_r2s.y); + float t1 = ((line_r2s.y - line_r2e.y) * (line_r1s.x - line_r2s.x) + (line_r2e.x - line_r2s.x) * (line_r1s.y - line_r2s.y)) / h; + float t2 = ((line_r1s.y - line_r1e.y) * (line_r1s.x - line_r2s.x) + (line_r1e.x - line_r1s.x) * (line_r1s.y - line_r2s.y)) / h; + + if (t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f) + { + if (bResolveStatic) + { + displacement.x += (1.0f - t1) * (line_r1e.x - line_r1s.x); + displacement.y += (1.0f - t1) * (line_r1e.y - line_r1s.y); + bCollision = true; + } + else + return true; + } + } + + + pos.x += displacement.x; + pos.y += displacement.y; + } + + return bCollision; + } + + std::vector meshTris; + std::vector vecPointsModel; + std::vector vecPointsWorld; + olc::GFX3D::vec3d pos; + + float fWidth; + float fHeight; + float fOriginX; + float fOriginY; + float fAngle; + }; + + bool LoadAssets(); + + std::map mapAssetTextures; + std::map mapAssetMeshes; + std::map mapAssetTransform; + + // Camera variables + olc::GFX3D::vec3d vCamera = { 0.0f, 0.0f, -3.0f }; + olc::GFX3D::vec3d vUp = { 0.0f, 1.0f, 0.0f }; + olc::GFX3D::vec3d vEye = { 0.0f, 0.0f, -3.0f }; + olc::GFX3D::vec3d vLookDir = { 0.0f, 0.0f, 1.0f }; + + // Ray Casting Parameters + olc::vf2d viewWorldTopLeft; + olc::vf2d viewWorldBottomRight; + + // Cloud movement variables + float fCloudOffsetX = 0.0f; + float fCloudOffsetY = 0.0f; + + // Mouse Control + olc::vf2d vOffset = { 0.0f, 0.0f }; + olc::vf2d vStartPan = { 0.0f, 0.0f }; + olc::vf2d vMouseOnGround = { 0.0f, 0.0f }; + float fScale = 1.0f; + + olc::vf2d GetMouseOnGround(const olc::vf2d &vMouseScreen); + + //cVehicle car; + olc::vf2d carvel; + olc::vf2d carpos; + float fSpeed = 0.0f; + float fAngle = 0.0f; + + std::list listAutomata; // Holds all automata, note its a pointer because we use polymorphism + + void SpawnPedestrian(int x, int y); + void SpawnVehicle(int x, int y); + + //cGameObjectQuad *goCar = nullptr; + //cGameObjectQuad *goObstacle = nullptr; + + //std::vector vecObstacles; + + cCityMap *pCity = nullptr; + + float fGlobalTime = 0.0f; + + // Editing Utilities + bool bEditMode = true; + int nMouseX = 0; + int nMouseY = 0; + + struct sCellLoc { int x, y; }; + std::unordered_set setSelectedCells; + + //std::list listDecalSmoke; + + //int nTrafficState = 0; + + void DoEditMode(float fElapsedTime); +}; + diff --git a/CarCrimeCity/Part2/cCell.cpp b/CarCrimeCity/Part2/cCell.cpp new file mode 100644 index 0000000..b5d173c --- /dev/null +++ b/CarCrimeCity/Part2/cCell.cpp @@ -0,0 +1,121 @@ +#include "cCell.h" + +#include "cCityMap.h" +#include "olcPixelGameEngine.h" +#include + +cCell::cCell() +{ +} + + +cCell::~cCell() +{ + // Cells own a list of automata navigation tracks + // but this will be destroyed when the cell is deleted +} + +cCell::cCell(cCityMap* map, int x, int y) +{ + pMap = map; + nWorldX = x; + nWorldY = y; + nCellType = CELL_BLANK; + + // Connect internal nodes + for (int i = 0; i < 49; i++) + pNaviNodes[i] = pMap->GetAutoNodeBase(x, y) + i; + + // Link cell into maps node pool + if (y > 0) + { + for (int i = 0; i < 7; i++) + pNaviNodes[i] = pMap->GetAutoNodeBase(x, y - 1) + 42 + i; + } + else + { + for (int i = 0; i < 7; i++) + pNaviNodes[i] = nullptr; + } + + if (x > 0) + { + // Link West side + for (int i = 0; i < 7; i++) + pNaviNodes[i * 7] = pMap->GetAutoNodeBase(x - 1, y) + 6 + i * 7; + } + else + { + for (int i = 0; i < 7; i++) + pNaviNodes[i * 7] = nullptr; + } + + // South Side + if (y < pMap->GetHeight() - 1) + { + + } + else + { + for (int i = 0; i < 7; i++) + pNaviNodes[42 + i] = nullptr; + } + + // East Side + if (x < pMap->GetWidth() - 1) + { + } + else + { + for (int i = 0; i < 7; i++) + pNaviNodes[6 + i * 7] = nullptr; + } + + // Unused Nodes + pNaviNodes[9] = nullptr; + pNaviNodes[11] = nullptr; + pNaviNodes[15] = nullptr; + pNaviNodes[19] = nullptr; + pNaviNodes[29] = nullptr; + pNaviNodes[33] = nullptr; + pNaviNodes[37] = nullptr; + pNaviNodes[39] = nullptr; + pNaviNodes[0] = nullptr; + pNaviNodes[6] = nullptr; + pNaviNodes[42] = nullptr; + pNaviNodes[48] = nullptr; + +} + + +bool cCell::LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms) +{ + return false; +} + +bool cCell::Update(float fElapsedTime) +{ + return false; +} + +bool cCell::DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe) +{ + return false; +} + +bool cCell::DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe) +{ + return false; +} + +bool cCell::DrawDebug(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe) +{ + + + return false; +} + +void cCell::CalculateAdjacency() +{ + +} diff --git a/CarCrimeCity/Part2/cCell.h b/CarCrimeCity/Part2/cCell.h new file mode 100644 index 0000000..6b70298 --- /dev/null +++ b/CarCrimeCity/Part2/cCell.h @@ -0,0 +1,60 @@ +#pragma once + +#include + +#include "olcPixelGameEngine.h" +#include "olcPGEX_Graphics3D.h" + +#include "cAutomata.h" + + +class cCityMap; + +enum CellType +{ + CELL_BLANK, + CELL_GRASS, + CELL_CONCRETE, + CELL_WATER, + CELL_BUILDING, + CELL_ROAD, + CELL_PAVEMENT, +}; + +class cCell +{ +public: + cCell(); + cCell(cCityMap* map, int x, int y); + ~cCell(); + +protected: + cCityMap* pMap = nullptr; + +public: + int nWorldX = 0; + int nWorldY = 0; + bool bSolid = false; + CellType nCellType = CELL_BLANK; + + // This cell may actuall be occupied by a multi-cell body + // so this pointer points to the host cell that contains + // that body + cCell* pHostCell = nullptr; + + // Each cell links to 20 automata transport nodes, 5 on each side + cAuto_Node* pNaviNodes[49]; + + // Each cell can have a number of automata transport tracks, it owns them + // These connect nodes together as determined by the cell + std::list listTracks; + +public: + virtual void CalculateAdjacency(); + virtual bool LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + virtual bool Update(float fElapsedTime); + virtual bool DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawDebug(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); +}; + diff --git a/CarCrimeCity/Part2/cCell_Building.cpp b/CarCrimeCity/Part2/cCell_Building.cpp new file mode 100644 index 0000000..151f7d6 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Building.cpp @@ -0,0 +1,53 @@ +#include "cCell_Building.h" + + + +cCell_Building::cCell_Building(const std::string &name, cCityMap* map, int x, int y) : cCell(map, x, y) +{ + sName = name; +} + + +cCell_Building::~cCell_Building() +{ +} + +void cCell_Building::CalculateAdjacency() +{ +} + +bool cCell_Building::LinkAssets(std::map& mapTextures, std::map& mapMesh, std::map &mapTransforms) +{ + texture = mapTextures[sName]; + mesh = mapMesh[sName]; + transform = mapTransforms[sName]; + return false; +} + +bool cCell_Building::Update(float fElapsedTime) +{ + return false; +} + +bool cCell_Building::DrawBase(olc::PixelGameEngine * pge, olc::GFX3D::PipeLine & pipe) +{ + olc::GFX3D::mat4x4 matTranslate = olc::GFX3D::Math::Mat_MakeTranslation((float)nWorldX, (float)nWorldY, 0.0f); + olc::GFX3D::mat4x4 matWorld = olc::GFX3D::Math::Mat_MultiplyMatrix(transform, matTranslate); + pipe.SetTransform(matWorld); + if (texture != nullptr) + { + pipe.SetTexture(texture); + pipe.Render(mesh->tris,olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_LIGHTS); + } + else + { + pipe.Render(mesh->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_FLAT | olc::GFX3D::RENDER_LIGHTS); + } + return false; +} + +bool cCell_Building::DrawAlpha(olc::PixelGameEngine * pge, olc::GFX3D::PipeLine & pipe) +{ + + return false; +} diff --git a/CarCrimeCity/Part2/cCell_Building.h b/CarCrimeCity/Part2/cCell_Building.h new file mode 100644 index 0000000..8ddd823 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Building.h @@ -0,0 +1,25 @@ +#pragma once +#include "cCell.h" +#include "olcPGEX_Graphics3D.h" + + +class cCell_Building : public cCell +{ +public: + cCell_Building(const std::string &name, cCityMap* map, int x, int y); + ~cCell_Building(); + +private: + std::string sName; + olc::Sprite* texture = nullptr; + olc::GFX3D::mesh* mesh = nullptr; + olc::GFX3D::mat4x4 transform; + +public: + virtual void CalculateAdjacency(); + virtual bool LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + virtual bool Update(float fElapsedTime); + virtual bool DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); +}; + diff --git a/CarCrimeCity/Part2/cCell_Plane.cpp b/CarCrimeCity/Part2/cCell_Plane.cpp new file mode 100644 index 0000000..34fc1b8 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Plane.cpp @@ -0,0 +1,49 @@ +#include "cCell_Plane.h" + + + +cCell_Plane::cCell_Plane(cCityMap* map, int x, int y, CELL_PLANE type) : cCell(map, x, y) +{ + bSolid = false; + nType = type; + if (nType == PLANE_GRASS) nCellType = CELL_GRASS; + if (nType == PLANE_ASPHALT) nCellType = CELL_PAVEMENT; +} + + +cCell_Plane::~cCell_Plane() +{ +} + +bool cCell_Plane::LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms) +{ + sprGrass = mapTextures["Grass"]; + sprPavement = mapTextures["Pavement"]; + meshUnitQuad = mapMesh["UnitQuad"]; + return true; +} + +bool cCell_Plane::Update(float fElapsedTime) +{ + return false; +} + +bool cCell_Plane::DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe) +{ + olc::GFX3D::mat4x4 matWorld; + matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)nWorldX, (float)nWorldY, 0.0f); + pipe.SetTransform(matWorld); + + if(nType == PLANE_GRASS) + pipe.SetTexture(sprGrass); + else + pipe.SetTexture(sprPavement); + + pipe.Render(meshUnitQuad->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED); + return false; +} + +bool cCell_Plane::DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe) +{ + return false; +} diff --git a/CarCrimeCity/Part2/cCell_Plane.h b/CarCrimeCity/Part2/cCell_Plane.h new file mode 100644 index 0000000..46abd0e --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Plane.h @@ -0,0 +1,34 @@ +#pragma once +#include "cCell.h" +#include "olcPixelGameEngine.h" +#include "olcPGEX_Graphics3D.h" +#include + + +enum CELL_PLANE +{ + PLANE_GRASS, + PLANE_ASPHALT +}; + +class cCell_Plane : public cCell +{ +public: + cCell_Plane(cCityMap* map, int x, int y, CELL_PLANE type); + ~cCell_Plane(); + +protected: + CELL_PLANE nType = PLANE_GRASS; + +private: + olc::GFX3D::mesh* meshUnitQuad = nullptr; + olc::Sprite* sprGrass = nullptr; + olc::Sprite* sprPavement = nullptr; + +public: + virtual bool LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + virtual bool Update(float fElapsedTime); + virtual bool DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); +}; + diff --git a/CarCrimeCity/Part2/cCell_Road.cpp b/CarCrimeCity/Part2/cCell_Road.cpp new file mode 100644 index 0000000..0b27721 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Road.cpp @@ -0,0 +1,812 @@ +#include "cCell_Road.h" +#include "cCityMap.h" + + +cCell_Road::cCell_Road(cCityMap* map, int x, int y) : cCell(map, x, y) +{ + bSolid = false; + nCellType = CELL_ROAD; +} + +cCell_Road::~cCell_Road() +{ +} + +void cCell_Road::CalculateAdjacency() +{ + + // Calculate suitable road junction type + auto r = [&](int i, int j) + { + return (pMap->Cell(nWorldX + i, nWorldY + j) != nullptr && pMap->Cell(nWorldX + i, nWorldY + j)->nCellType == CELL_ROAD); + }; + + if (r(0, -1) && r(0, +1) && !r(-1, 0) && !r(+1, 0)) nRoadType = ROAD_V; + if (!r(0, -1) && !r(0, +1) && r(-1, 0) && r(+1, 0)) nRoadType =ROAD_H; + if (!r(0, -1) && r(0, +1) && !r(-1, 0) && r(+1, 0)) nRoadType = ROAD_C1; + if (!r(0, -1) && r(0, +1) && r(-1, 0) && r(+1, 0)) nRoadType =ROAD_T1; + if (!r(0, -1) && r(0, +1) && r(-1, 0) && !r(+1, 0)) nRoadType = ROAD_C2; + if (r(0, -1) && r(0, +1) && !r(-1, 0) && r(+1, 0)) nRoadType = ROAD_T2; + if (r(0, -1) && r(0, +1) && r(-1, 0) && r(+1, 0)) nRoadType = ROAD_X; + if (r(0, -1) && r(0, +1) && r(-1, 0) && !r(+1, 0)) nRoadType = ROAD_T3; + if (r(0, -1) && !r(0, +1) && !r(-1, 0) && r(+1, 0)) nRoadType = ROAD_C3; + if (r(0, -1) && !r(0, +1) && r(-1, 0) && r(+1, 0)) nRoadType = ROAD_T4; + if (r(0, -1) && !r(0, +1) && r(-1, 0) && !r(+1, 0)) nRoadType = ROAD_C4; + + // Add navigation tracks based on type + + auto AddTrack = [&](int n1, int n2) -> cAuto_Track* + { + if (pNaviNodes[n1] == nullptr || pNaviNodes[n2] == nullptr) + { + // Can't add track + return nullptr; + } + else + { + // Nodes exist so add track + cAuto_Track t; + t.node[0] = pNaviNodes[n1]; + t.node[1] = pNaviNodes[n2]; + t.cell = this; + t.fTrackLength = (pNaviNodes[n1]->pos - pNaviNodes[n2]->pos).mag(); + listTracks.push_back(t); + + // Add pointers to track to start and end nodes + pNaviNodes[n1]->listTracks.push_back(&listTracks.back()); + pNaviNodes[n2]->listTracks.push_back(&listTracks.back()); + + return &listTracks.back(); + } + }; + + // Ensure list of tracks for this cell is clear + listTracks.clear(); + + // Add tracks depending on junction type + pSafePedestrianTrack = nullptr; + pSafeCarTrack = nullptr; + pSafeChaseTrack = nullptr; + + // Add Pedestrian Tracks + switch (nRoadType) + { + case ROAD_H: pSafePedestrianTrack = AddTrack(7, 13); AddTrack(41, 35); break; + case ROAD_V: pSafePedestrianTrack = AddTrack(1, 43); AddTrack(5, 47); break; + + case ROAD_C1: pSafePedestrianTrack = AddTrack(43, 8); AddTrack(8, 13); AddTrack(47, 40); AddTrack(40, 41); break; + case ROAD_C2: AddTrack(7, 12); AddTrack(12, 47); pSafePedestrianTrack = AddTrack(35, 36); AddTrack(36, 43); break; + case ROAD_C3: AddTrack(1, 36); pSafePedestrianTrack = AddTrack(36, 41); AddTrack(5, 12); AddTrack(12, 13); break; + case ROAD_C4: AddTrack(35, 40); AddTrack(40, 5); pSafePedestrianTrack = AddTrack(7, 8); AddTrack(8, 1); break; + + case ROAD_T1: pSafePedestrianTrack = AddTrack(7, 8); AddTrack(8, 12); AddTrack(12, 13); AddTrack(35, 36); AddTrack(36, 38); AddTrack(38, 40); AddTrack(40, 41); AddTrack(8, 22); AddTrack(22, 36); AddTrack(36, 43); AddTrack(12, 26); AddTrack(26, 40); AddTrack(40, 47); break; + case ROAD_T2: pSafePedestrianTrack = AddTrack(1, 8); AddTrack(8, 36); AddTrack(36, 43); AddTrack(5, 12); AddTrack(12, 26); AddTrack(26, 40); AddTrack(40, 47); AddTrack(8, 10); AddTrack(10, 12); AddTrack(12, 13); AddTrack(36, 38), AddTrack(38, 40); AddTrack(40, 41); break; + case ROAD_T3: pSafePedestrianTrack = AddTrack(5, 12); AddTrack(12, 40); AddTrack(40, 47); AddTrack(1, 8); AddTrack(8, 22); AddTrack(22, 36); AddTrack(36, 43); AddTrack(12, 10); AddTrack(10, 8); AddTrack(8, 7); AddTrack(40, 38); AddTrack(38, 36); AddTrack(36, 35); break; + case ROAD_T4: pSafePedestrianTrack = AddTrack(35, 36); AddTrack(36, 40); AddTrack(40, 41); AddTrack(7, 8); AddTrack(8, 10); AddTrack(10, 12); AddTrack(12, 13); AddTrack(36, 22); AddTrack(22, 8); AddTrack(8, 1); AddTrack(40, 26); AddTrack(26, 12); AddTrack(12, 5); break; + + case ROAD_X: AddTrack(35, 36); AddTrack(36, 38); AddTrack(38, 40); AddTrack(40, 41); AddTrack(7, 8); AddTrack(8, 10); AddTrack(10, 12); AddTrack(12, 13); AddTrack(36, 22); AddTrack(22, 8); AddTrack(8, 1); AddTrack(40, 26); AddTrack(26, 12); AddTrack(12, 5); pSafePedestrianTrack = AddTrack(36, 43); AddTrack(40, 47); break; + } + + + // Add Chase Tracks + switch (nRoadType) + { + case ROAD_H: AddTrack(21, 27); break; + case ROAD_V: AddTrack(3, 45); break; + + case ROAD_C1: AddTrack(45, 24); AddTrack(24, 27); break; + case ROAD_C2: AddTrack(21, 24); AddTrack(24, 45); break; + case ROAD_C3: AddTrack(3, 24); AddTrack(24, 27); break; + case ROAD_C4: AddTrack(21, 24); AddTrack(24, 3); break; + + case ROAD_T1: AddTrack(21, 24); AddTrack(24, 27); AddTrack(24, 45); break; + case ROAD_T2: AddTrack(3, 24); AddTrack(24, 45); AddTrack(24, 27); break; + case ROAD_T3: AddTrack(3, 24); AddTrack(24, 45); AddTrack(24, 21); break; + case ROAD_T4: AddTrack(21, 24); AddTrack(24, 27); AddTrack(24, 3); break; + + case ROAD_X: AddTrack(3, 24); AddTrack(27, 24); AddTrack(45, 24); AddTrack(21, 24); break; + } + + + //// Road traffic tracks + switch (nRoadType) + { + case ROAD_H: pSafeCarTrack = AddTrack(14, 20); AddTrack(28, 34); break; + case ROAD_V: AddTrack(2, 44); pSafeCarTrack = AddTrack(4, 46); break; + + case ROAD_C1: pSafeCarTrack = AddTrack(44, 16); AddTrack(16, 20); AddTrack(46, 32); AddTrack(32, 34); break; + case ROAD_C2: pSafeCarTrack = AddTrack(14, 18); AddTrack(18, 46); AddTrack(28, 30); AddTrack(30, 44); break; + case ROAD_C3: AddTrack(2, 30); AddTrack(30, 34); pSafeCarTrack = AddTrack(4, 18); AddTrack(18, 20); break; + case ROAD_C4: AddTrack(2, 16); AddTrack(16, 14); pSafeCarTrack = AddTrack(4, 32); AddTrack(32, 28); break; + + + case ROAD_T1: AddTrack(14, 16); AddTrack(16, 18); AddTrack(18, 20); AddTrack(28, 30); AddTrack(30, 32); AddTrack(32, 34); + AddTrack(16, 30); AddTrack(30, 44); AddTrack(18, 32); AddTrack(32, 46); break; + + case ROAD_T4: AddTrack(14, 16); AddTrack(16, 18); AddTrack(18, 20); AddTrack(28, 30); AddTrack(30, 32); AddTrack(32, 34); + AddTrack(16, 30); AddTrack(16, 2); AddTrack(18, 32); AddTrack(18, 4); break; + + case ROAD_T2: AddTrack(2, 16); AddTrack(16, 30); AddTrack(30, 44); AddTrack(4, 18); AddTrack(18, 32); AddTrack(32, 46); + AddTrack(16, 18); AddTrack(18, 20); AddTrack(30, 32); AddTrack(32, 34); break; + + case ROAD_T3: AddTrack(2, 16); AddTrack(16, 30); AddTrack(30, 44); AddTrack(4, 18); AddTrack(18, 32); AddTrack(32, 46); + AddTrack(14, 16); AddTrack(16, 18); AddTrack(28, 30); AddTrack(30, 32); break; + + case ROAD_X: + AddTrack(2, 16); AddTrack(16, 30); AddTrack(30, 44); AddTrack(4, 18); AddTrack(18, 32); AddTrack(32, 46); + AddTrack(14, 16); AddTrack(16, 18); AddTrack(18, 20); AddTrack(28, 30); AddTrack(30, 32); AddTrack(32, 34); break; + } + + + // Stop Patterns, here we go, loads of data... :( + + // .PO.OP. + // PP.P.PP + // O.O.O.O + // .P...P. + // O.O.O.O + // PP.P.PP + // .PO.OP. + + // .PO.OP. + // PP.P.PP + // O.X.X.O + // .P...P. + // O.X.X.O + // PP.P.PP + // .PO.OP. + + // .PO.OP. + // PP.X.PP + // O.X.X.O + // .X...X. + // O.X.X.O + // PP.X.PP + // .PO.OP. + + auto stopmap = [&](const std::string &s) + { + StopPattern p; + for (size_t i = 0; i < s.size(); i++) + p.bStop[i] = (s[i] == 'X'); + return p; + }; + + switch (nRoadType) + { + case ROAD_H: + case ROAD_V: + case ROAD_C1: + case ROAD_C2: + case ROAD_C3: + case ROAD_C4: + // Allow all + /*vStopPattern.push_back( + stopmap( + ".PO.OP." + "PP.P.PP" + "O.O.O.O" + ".P...P." + "O.O.O.O" + "PP.P.PP" + ".PO.OP."));*/ + break; + + case ROAD_X: + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "O.O.O.O" + ".X...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".X...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow North Traffic + vStopPattern.push_back( + stopmap( + ".PX.OP." + "PP.X.PP" + "X.X.O.O" + ".X...X." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain North Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.O.O" + ".X...X." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow EAST Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...X." + "O.O.O.O" + "PP.X.PP" + ".PX.OP.")); + // Drain East Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...X." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".X...X." + "O.O.X.X" + "PP.X.PP" + ".PO.XP.")); + // Drain SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".X...X." + "O.O.X.X" + "PP.X.PP" + ".PX.XP.")); + + break; + + case ROAD_T1: + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow West Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "O.O.O.O" + ".X...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain West Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.O.O.O" + ".X...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow EAST Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".X...X." + "O.O.O.O" + "PP.X.PP" + ".PX.OP.")); + // Drain East Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".X...X." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.O.O.O" + ".X...X." + "O.O.X.X" + "PP.X.PP" + ".PO.XP.")); + // Drain SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.O.O.O" + ".X...X." + "O.O.X.X" + "PP.X.PP" + ".PX.XP.")); + break; + + case ROAD_T2: + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".P...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow North Traffic + vStopPattern.push_back( + stopmap( + ".PX.OP." + "PP.X.PP" + "X.X.O.O" + ".P...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain North Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.O.O" + ".P...X." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow EAST Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".P...X." + "X.O.O.O" + "PP.X.PP" + ".PX.OP.")); + // Drain East Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".P...X." + "X.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".P...X." + "X.O.X.X" + "PP.X.PP" + ".PO.XP.")); + // Drain SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".P...X." + "X.O.X.X" + "PP.X.PP" + ".PX.XP.")); + break; + case ROAD_T3: + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...P." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "O.O.O.X" + ".X...P." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.X" + ".X...P." + "X.X.O.X" + "PP.X.PP" + ".PX.OP.")); + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow North Traffic + vStopPattern.push_back( + stopmap( + ".PX.OP." + "PP.X.PP" + "X.X.O.X" + ".X...P." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + // Drain North Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.O.X" + ".X...P." + "O.O.O.X" + "PP.X.PP" + ".PX.OP.")); + + // Allow SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...P." + "O.O.X.X" + "PP.X.PP" + ".PO.XP.")); + // Drain SOUTH Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...P." + "O.O.X.X" + "PP.X.PP" + ".PX.XP.")); + break; + + case ROAD_T4: + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Allow West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "O.O.O.O" + ".X...X." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain West Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.O.O" + ".X...X." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Allow North Traffic + vStopPattern.push_back( + stopmap( + ".PX.OP." + "PP.X.PP" + "X.X.O.O" + ".X...X." + "O.O.O.X" + "PP.P.PP" + ".PX.XP.")); + // Drain North Traffic + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.O.O" + ".X...X." + "O.O.O.X" + "PP.P.PP" + ".PX.XP.")); + // Allow Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.P.PP" + "X.X.X.X" + ".P...P." + "X.X.X.X" + "PP.P.PP" + ".PX.XP.")); + // Drain Pedestrians + vStopPattern.push_back( + stopmap( + ".PX.XP." + "PP.X.PP" + "X.X.X.X" + ".X...X." + "X.X.X.X" + "PP.X.PP" + ".PX.XP.")); + // Allow EAST Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...X." + "O.O.O.O" + "PP.P.PP" + ".PX.XP.")); + // Drain East Traffic + vStopPattern.push_back( + stopmap( + ".PO.XP." + "PP.X.PP" + "X.O.X.X" + ".X...X." + "O.O.O.X" + "PP.P.PP" + ".PX.XP.")); + break; + + + } + +} + +bool cCell_Road::LinkAssets(std::map& mapTextures, std::map& mapMesh, std::map &mapTransforms) +{ + meshUnitQuad = mapMesh["UnitQuad"]; + sprRoadTex[ROAD_V] = mapTextures["Road_V"]; + sprRoadTex[ROAD_H] = mapTextures["Road_H"]; + sprRoadTex[ROAD_C1] = mapTextures["Road_C1"]; + sprRoadTex[ROAD_T1] = mapTextures["Road_T1"]; + sprRoadTex[ROAD_C2] = mapTextures["Road_C2"]; + sprRoadTex[ROAD_T2] = mapTextures["Road_T2"]; + sprRoadTex[ROAD_X] = mapTextures["Road_X"]; + sprRoadTex[ROAD_T3] = mapTextures["Road_T3"]; + sprRoadTex[ROAD_C3] = mapTextures["Road_C3"]; + sprRoadTex[ROAD_T4] = mapTextures["Road_T4"]; + sprRoadTex[ROAD_C4] = mapTextures["Road_C4"]; + return false; +} + +bool cCell_Road::Update(float fElapsedTime) +{ + if (vStopPattern.empty()) + return false; + + fStopPatternTimer += fElapsedTime; + if (fStopPatternTimer >= 5.0f) + { + fStopPatternTimer -= 5.0f; + nCurrentStopPattern++; + nCurrentStopPattern %= vStopPattern.size(); + for (int i = 0; i < 49; i++) + if(pNaviNodes[i] != nullptr) + pNaviNodes[i]->bBlock = vStopPattern[nCurrentStopPattern].bStop[i]; + } + + + return false; +} + +bool cCell_Road::DrawBase(olc::PixelGameEngine* pge, olc::GFX3D::PipeLine & pipe) +{ + olc::GFX3D::mat4x4 matWorld; + matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)nWorldX, (float)nWorldY, 0.0f); + pipe.SetTransform(matWorld); + pipe.SetTexture(sprRoadTex[nRoadType]); + pipe.Render(meshUnitQuad->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED); + return false; +} + +bool cCell_Road::DrawAlpha(olc::PixelGameEngine* pge, olc::GFX3D::PipeLine & pipe) +{ + return false; +} + +bool cCell_Road::DrawDebug(olc::PixelGameEngine* pge, olc::GFX3D::PipeLine & pipe) +{ + + + + // Draw Automata navigation tracks + for (auto &track : listTracks) + { + olc::GFX3D::vec3d p1 = { track.node[0]->pos.x, track.node[0]->pos.y, 0.0f }; + olc::GFX3D::vec3d p2 = { track.node[1]->pos.x, track.node[1]->pos.y, 0.0f }; + pipe.RenderLine(p1, p2, olc::CYAN); + } + + + for (int i = 0; i < 49; i++) + { + if (pNaviNodes[i] != nullptr) + { + olc::GFX3D::vec3d p1 = { pNaviNodes[i]->pos.x, pNaviNodes[i]->pos.y, 0.01f }; + pipe.RenderCircleXZ(p1, 0.03f, pNaviNodes[i]->bBlock ? olc::RED : olc::GREEN); + } + } + + return false; +} diff --git a/CarCrimeCity/Part2/cCell_Road.h b/CarCrimeCity/Part2/cCell_Road.h new file mode 100644 index 0000000..22abc7e --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Road.h @@ -0,0 +1,54 @@ +#pragma once +#include "cCell.h" + +enum RoadType +{ + ROAD_H, + ROAD_V, + ROAD_C1, + ROAD_C2, + ROAD_C3, + ROAD_C4, + ROAD_T1, + ROAD_T2, + ROAD_T3, + ROAD_T4, + ROAD_X, +}; + + +class cCell_Road : public cCell +{ +public: + cCell_Road(cCityMap* map, int x, int y); + ~cCell_Road(); + +private: + struct StopPattern + { + bool bStop[49]; + }; + +private: + bool bNeighboursAreRoads[4]; + + olc::GFX3D::mesh *meshUnitQuad = nullptr; + olc::Sprite* sprRoadTex[11]; + + std::vector vStopPattern; + int nCurrentStopPattern = 0; + float fStopPatternTimer = 0.0f; +public: + RoadType nRoadType = ROAD_X; + cAuto_Track* pSafeCarTrack = nullptr; + cAuto_Track* pSafePedestrianTrack = nullptr; + cAuto_Track* pSafeChaseTrack = nullptr; + + virtual void CalculateAdjacency(); + virtual bool LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + virtual bool Update(float fElapsedTime); + virtual bool DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawDebug(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); +}; + diff --git a/CarCrimeCity/Part2/cCell_Water.cpp b/CarCrimeCity/Part2/cCell_Water.cpp new file mode 100644 index 0000000..da3b863 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Water.cpp @@ -0,0 +1,91 @@ +#include "cCell_Water.h" +#include "cCityMap.h" + + +cCell_Water::cCell_Water(cCityMap* map, int x, int y) : cCell(map, x, y) +{ + nCellType = CELL_WATER; + bNeighboursAreWater[0] = false; + bNeighboursAreWater[1] = false; + bNeighboursAreWater[2] = false; + bNeighboursAreWater[3] = false; +} + + +cCell_Water::~cCell_Water() +{ +} + +bool cCell_Water::LinkAssets(std::map& mapTextures, std::map& mapMesh, std::map &mapTransforms) +{ + meshUnitQuad = mapMesh["UnitQuad"]; + meshWalls = mapMesh["WallsOut"]; + sprWater = mapTextures["Water"]; + sprSides = mapTextures["WaterSide"]; + sprClouds = mapTextures["Clouds"]; + return false; +} + +bool cCell_Water::Update(float fElapsedTime) +{ + return false; +} + +bool cCell_Water::DrawBase(olc::PixelGameEngine * pge, olc::GFX3D::PipeLine & pipe) +{ + olc::GFX3D::mat4x4 matWorld; + matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)nWorldX, (float)nWorldY, 0.0f); + pipe.SetTransform(matWorld); + pipe.SetTexture(sprSides); + if (!bNeighboursAreWater[1]) pipe.Render(meshWalls->tris, olc::GFX3D::RENDER_LIGHTS | olc::GFX3D::RENDER_CULL_CCW | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_DEPTH, 0, 2); + if (!bNeighboursAreWater[3]) pipe.Render(meshWalls->tris, olc::GFX3D::RENDER_LIGHTS | olc::GFX3D::RENDER_CULL_CCW | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_DEPTH, 2, 2); + if (!bNeighboursAreWater[2]) pipe.Render(meshWalls->tris, olc::GFX3D::RENDER_LIGHTS | olc::GFX3D::RENDER_CULL_CCW | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_DEPTH, 4, 2); + if (!bNeighboursAreWater[0]) pipe.Render(meshWalls->tris, olc::GFX3D::RENDER_LIGHTS | olc::GFX3D::RENDER_CULL_CCW | olc::GFX3D::RENDER_TEXTURED | olc::GFX3D::RENDER_DEPTH, 6, 2); + return false; +} + +bool cCell_Water::DrawAlpha(olc::PixelGameEngine * pge, olc::GFX3D::PipeLine & pipe) +{ + auto renderWater = [&](const int x, const int y, const olc::Pixel& pSource, const olc::Pixel& pDest) + { + float a = (float)(pSource.a / 255.0f) * 0.6f; + float c = 1.0f - a; + float r = a * (float)pSource.r + c * (float)pDest.r; + float g = a * (float)pSource.g + c * (float)pDest.g; + float b = a * (float)pSource.b + c * (float)pDest.b; + + a = 0.4f; + c = 1.0f - a; + olc::Pixel sky = sprClouds->GetPixel(x, y); + float sr = a * (float)sky.r + c * r; + float sg = a * (float)sky.g + c * g; + float sb = a * (float)sky.b + c * b; + + return olc::Pixel((uint8_t)sr, (uint8_t)sg, (uint8_t)sb); + }; + + pge->SetPixelMode(renderWater); + olc::GFX3D::mat4x4 matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)nWorldX, (float)nWorldY, 0.07f); + pipe.SetTransform(matWorld); + pipe.SetTexture(sprWater); + pipe.Render(meshUnitQuad->tris, olc::GFX3D::RENDER_CULL_CW | olc::GFX3D::RENDER_DEPTH | olc::GFX3D::RENDER_TEXTURED); + pge->SetPixelMode(olc::Pixel::NORMAL); + return false; +} + + +void cCell_Water::CalculateAdjacency() +{ + auto r = [&](int i, int j) + { + if (pMap->Cell(nWorldX + i, nWorldY + j) != nullptr) + return pMap->Cell(nWorldX + i, nWorldY + j)->nCellType == CELL_WATER; + else + return false; + }; + + bNeighboursAreWater[0] = r(0, -1); + bNeighboursAreWater[1] = r(+1, 0); + bNeighboursAreWater[2] = r(0, +1); + bNeighboursAreWater[3] = r(-1, 0); +} \ No newline at end of file diff --git a/CarCrimeCity/Part2/cCell_Water.h b/CarCrimeCity/Part2/cCell_Water.h new file mode 100644 index 0000000..35a85f2 --- /dev/null +++ b/CarCrimeCity/Part2/cCell_Water.h @@ -0,0 +1,25 @@ +#pragma once +#include "cCell.h" +class cCell_Water : public cCell +{ +public: + cCell_Water(cCityMap* map, int x, int y); + ~cCell_Water(); + +private: + olc::GFX3D::mesh* meshUnitQuad = nullptr; + olc::GFX3D::mesh* meshWalls = nullptr; + olc::Sprite* sprWater = nullptr; + olc::Sprite* sprSides = nullptr; + olc::Sprite* sprClouds = nullptr; + + bool bNeighboursAreWater[4]; + +public: + virtual void CalculateAdjacency(); + virtual bool LinkAssets(std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + virtual bool Update(float fElapsedTime); + virtual bool DrawBase(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); + virtual bool DrawAlpha(olc::PixelGameEngine *pge, olc::GFX3D::PipeLine &pipe); +}; + diff --git a/CarCrimeCity/Part2/cCityMap.cpp b/CarCrimeCity/Part2/cCityMap.cpp new file mode 100644 index 0000000..b4c1c54 --- /dev/null +++ b/CarCrimeCity/Part2/cCityMap.cpp @@ -0,0 +1,202 @@ +#include "cCityMap.h" + +#include + + + +cCityMap::cCityMap(int w, int h, std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms) +{ + CreateCity(w, h, mapTextures, mapMesh, mapTransforms); +} + +cCityMap::~cCityMap() +{ + ReleaseCity(); +} + +int cCityMap::GetWidth() +{ + return nWidth; +} + +int cCityMap::GetHeight() +{ + return nHeight; +} + +cCell* cCityMap::Cell(int x, int y) +{ + if (x >= 0 && x < nWidth && y >= 0 && y < nHeight) + return pCells[y*nWidth + x]; + else + return nullptr; +} + +cCell* cCityMap::Replace(int x, int y, cCell* cell) +{ + if (cell == nullptr) + return nullptr; + + if (pCells[y * nWidth + x] != nullptr) + delete pCells[y * nWidth + x]; + + pCells[y * nWidth + x] = cell; + return cell; +} + +void cCityMap::CreateCity(int w, int h, std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms) +{ + ReleaseCity(); + nWidth = w; + nHeight = h; + pCells = new cCell*[nHeight * nWidth]; + + // Create Navigation Node Pool, assumes 5 nodes on east and south + // side of each cell. The City owns these nodes, and cells in the + // city borrow them and link to them as required + pNodes = new cAuto_Node[nHeight * nWidth * 49]; + + // The cell has 49 nodes, though some are simply unused. This is less memory + // efficient certainly, but makes code more intuitive and easier to write + + for (int x = 0; x < nWidth; x++) + { + for (int y = 0; y < nHeight; y++) + { + // Nodes sit between cells, therefore each create nodes along + // the east and southern sides of the cell. This assumes that + // navigation along the top and left boundaries of the map + // will not occur. And it shouldnt, as its water + + int idx = (y * nWidth + x) * 49; + + for (int dx = 0; dx < 7; dx++) + { + float off_x = 0.0f; + switch (dx) + { + case 0: off_x = 0.000f; break; + case 1: off_x = 0.083f; break; + case 2: off_x = 0.333f; break; + case 3: off_x = 0.500f; break; + case 4: off_x = 0.667f; break; + case 5: off_x = 0.917f; break; + case 6: off_x = 1.000f; break; + } + + + for (int dy = 0; dy < 7; dy++) + { + float off_y = 0.0f; + switch (dy) + { + case 0: off_y = 0.000f; break; + case 1: off_y = 0.083f; break; + case 2: off_y = 0.333f; break; + case 3: off_y = 0.500f; break; + case 4: off_y = 0.667f; break; + case 5: off_y = 0.917f; break; + case 6: off_y = 1.000f; break; + } + + pNodes[idx + dy * 7 + dx].pos = { (float)x + off_x, (float)y + off_y }; + pNodes[idx + dy * 7 + dx].bBlock = false; + } + } + } + } + + + // Now create default Cell + for (int x = 0; x < nWidth; x++) + { + for (int y = 0; y < nHeight; y++) + { + // Default city, everything is grass + pCells[y * nWidth + x] = new cCell_Plane(this, x, y, PLANE_GRASS); + + // Give the cell the opportunity to locally reference the resources it needs + pCells[y * nWidth + x]->LinkAssets(mapTextures, mapMesh, mapTransforms); + } + } + +} + +cAuto_Node* cCityMap::GetAutoNodeBase(int x, int y) +{ + return pNodes + (y * nWidth + x) * 49; +} + +void cCityMap::RemoveAllTracks() +{ + for (int i = 0; i < nWidth * nHeight * 49; i++) + { + pNodes[i].listTracks.clear(); + } +} + +void cCityMap::ReleaseCity() +{ + for (int x = 0; x < nWidth; x++) + { + for (int y = 0; y < nHeight; y++) + { + // Erase any tracks attached to nodes + for(int i=0; i<49; i++) + Cell(x, y)->pNaviNodes[i]->listTracks.clear(); + + // Release individual cell objects + delete pCells[y * nWidth + x]; + } + } + + // Release array of cell pointers + if (pCells != nullptr) delete pCells; + + // Release array of automata navigation nodes + if (pNodes != nullptr) delete pNodes; + + nWidth = 0; + nHeight = 0; +} + + +bool cCityMap::SaveCity(std::string sFilename) +{ + /*std::ofstream file(sFilename, std::ios::out | std::ios::binary); + if (!file.is_open()) return false; + + file.write((char*)&m_nWidth, sizeof(int)); + file.write((char*)&m_nHeight, sizeof(int)); + + for (int x = 0; x < m_nWidth; x++) + { + for (int y = 0; y < m_nHeight; y++) + { + file.write((char*)Cell(x, y), sizeof(cCityCell)); + } + }*/ + + return true; +} + +bool cCityMap::LoadCity(std::string sFilename) +{ + /*std::ifstream file(sFilename, std::ios::in | std::ios::binary); + if (!file.is_open()) return false; + + int w, h; + file.read((char*)&w, sizeof(int)); + file.read((char*)&h, sizeof(int)); + CreateCity(w, h); + + for (int x = 0; x < m_nWidth; x++) + { + for (int y = 0; y < m_nHeight; y++) + { + file.read((char*)Cell(x, y), sizeof(cCityCell)); + } + }*/ + + return true; +} \ No newline at end of file diff --git a/CarCrimeCity/Part2/cCityMap.h b/CarCrimeCity/Part2/cCityMap.h new file mode 100644 index 0000000..828a23e --- /dev/null +++ b/CarCrimeCity/Part2/cCityMap.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +#include "olcPixelGameEngine.h" +#include "olcPGEX_Graphics3D.h" +#include "cCell.h" +#include "cCell_Plane.h" +#include "cCell_Water.h" +#include "cCell_Road.h" +#include "cCell_Building.h" + +/* + This class holds the definition of a map. The map data is actually + stored within this clap, as well as accessors to access the individual + map cells +*/ +class cCityMap +{ +public: + // Construct a "blank" city w units wide by h units high + cCityMap(int w, int h, std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + + // Cleans up city, like Batman + ~cCityMap(); + +public: + // Save the current city to a file, this will overwrite an existing + // city file without warning. Returns true if successful + bool SaveCity(std::string sFilename); + + // Load a city from file and replace current city with it, retuns + // true if successful + bool LoadCity(std::string sFilename); + +public: + // Return width of city in cells + int GetWidth(); + // Return height of city in cells + int GetHeight(); + // Return a specific cell reference if inside city limits, or nullptr + cCell* Cell(int x, int y); + // Replace a specific cell + cCell* Replace(int x, int y, cCell* cell); + + cAuto_Node* GetAutoNodeBase(int x, int y); + + void RemoveAllTracks(); + +private: + int nWidth = 0; + int nHeight = 0; + cCell **pCells = nullptr; + cAuto_Node *pNodes = nullptr; + +private: + // Creates a "default" city of specified size + void CreateCity(int w, int h, std::map &mapTextures, std::map &mapMesh, std::map &mapTransforms); + // Destroy city + void ReleaseCity(); +}; + diff --git a/CarCrimeCity/Part2/cGameSettings.cpp b/CarCrimeCity/Part2/cGameSettings.cpp new file mode 100644 index 0000000..1ca52a5 --- /dev/null +++ b/CarCrimeCity/Part2/cGameSettings.cpp @@ -0,0 +1,156 @@ +#include "cGameSettings.h" + + + +cGameSettings::cGameSettings() +{ +} + +cGameSettings::~cGameSettings() +{ +} + +bool cGameSettings::LoadConfigFile(std::string sFile) +{ + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + + // Load game settings file + int r = luaL_loadfile(L, sFile.c_str()); + if (r != LUA_OK) + { + std::string errormsg = lua_tostring(L, -1); + std::cout << errormsg << std::endl; + return false; + } + + // Execute it + int i = lua_pcall(L, 0, LUA_MULTRET, 0); + if (i != LUA_OK) + { + std::string errormsg = lua_tostring(L, -1); + std::cout << errormsg << std::endl; + return false; + } + + lua_getglobal(L, "PixelWidth"); + if (lua_isinteger(L, -1)) cGameSettings::nPixelWidth = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "PixelHeight"); + if (lua_isinteger(L, -1)) cGameSettings::nPixelHeight = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "ScreenWidth"); + if (lua_isinteger(L, -1)) cGameSettings::nScreenWidth = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "ScreenHeight"); + if (lua_isinteger(L, -1)) cGameSettings::nScreenHeight = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "DefaultMapWidth"); + if (lua_isinteger(L, -1)) cGameSettings::nDefaultMapWidth = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "DefaultMapHeight"); + if (lua_isinteger(L, -1)) cGameSettings::nDefaultMapHeight = (int)lua_tointeger(L, -1); + + lua_getglobal(L, "DefaultCityFile"); + if (lua_isstring(L, -1)) cGameSettings::sDefaultCityFile = lua_tostring(L, -1); + + lua_getglobal(L, "FullScreen"); + if (lua_isboolean(L, -1)) cGameSettings::bFullScreen = lua_toboolean(L, -1); + + + //// Load System Texture files + + // Load Texture Assets + lua_getglobal(L, "Textures"); // -1 Table "Teams" + if (lua_istable(L, -1)) + { + lua_pushnil(L); // -2 Key Nil : -1 Table "Teams" + + while (lua_next(L, -2) != 0) // -1 Table : -2 Key "TeamName" : -3 Table "Teams" + { + sAssetTexture texture; + int stage = 0; + if (lua_istable(L, -1)) + { + lua_gettable(L, -1); // -1 Table : -2 Table Value : -3 Key "TeamName" : -4 Table "Teams" + lua_pushnil(L); // -1 Key Nil : -2 Table : -3 Table Value : -4 Key "TeamName" : -5 Table "Teams" + while (lua_next(L, -2) != 0) // -1 Value "BotFile" : -2 Key Nil : -3 Table : -4 Table Value : -5 Key "TeamName" : -6 Table "Teams" + { + if (stage == 0) texture.sName = lua_tostring(L, -1); + if (stage == 1) texture.sFile = lua_tostring(L, -1); + lua_pop(L, 1); // -1 Key Nil : -2 Table : -3 Table Value : -4 Key "TeamName" : -5 Table "Teams" + stage++; + } + } + lua_pop(L, 1); // -1 Table : -2 Table Value : -3 Key "TeamName" : -4 Table "Teams" + vecAssetTextures.push_back(texture); + } + } + + auto GroupLoadAssets = [L](const std::string &group, std::vector &vec) + { + lua_getglobal(L, group.c_str()); + if (lua_istable(L, -1)) + { + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + sAssetModel model; + int stage = 0; + if (lua_istable(L, -1)) + { + lua_gettable(L, -1); + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + if (stage == 0) model.sCreator = lua_tostring(L, -1); + if (stage == 1) model.sDescription = lua_tostring(L, -1); + if (stage == 2) model.sModelOBJ = lua_tostring(L, -1); + if (stage == 3) model.sModelPNG = lua_tostring(L, -1); + + if (stage == 4) model.fRotate[0] = (float)lua_tonumber(L, -1); + if (stage == 5) model.fRotate[1] = (float)lua_tonumber(L, -1); + if (stage == 6) model.fRotate[2] = (float)lua_tonumber(L, -1); + + if (stage == 7) model.fScale[0] = (float)lua_tonumber(L, -1); + if (stage == 8) model.fScale[1] = (float)lua_tonumber(L, -1); + if (stage == 9) model.fScale[2] = (float)lua_tonumber(L, -1); + + if (stage == 10) model.fTranslate[0] = (float)lua_tonumber(L, -1); + if (stage == 11) model.fTranslate[1] = (float)lua_tonumber(L, -1); + if (stage == 12) model.fTranslate[2] = (float)lua_tonumber(L, -1); + lua_pop(L, 1); + stage++; + } + } + lua_pop(L, 1); + vec.push_back(model); + } + } + }; + + // Load Building Assets + GroupLoadAssets("Buildings", vecAssetBuildings); + + // Load Vehicle Assets + GroupLoadAssets("Vehicles", vecAssetVehicles); + + + lua_close(L); + + return true; +} + +int cGameSettings::nScreenWidth = 768; +int cGameSettings::nScreenHeight = 480; +int cGameSettings::nPixelWidth = 2; +int cGameSettings::nPixelHeight = 2; +bool cGameSettings::bFullScreen = false; + +int cGameSettings::nDefaultMapWidth = 64; +int cGameSettings::nDefaultMapHeight = 32; +std::string cGameSettings::sDefaultCityFile = ""; + +std::vector cGameSettings::vecAssetTextures; +std::vector cGameSettings::vecAssetBuildings; +std::vector cGameSettings::vecAssetVehicles; \ No newline at end of file diff --git a/CarCrimeCity/Part2/cGameSettings.h b/CarCrimeCity/Part2/cGameSettings.h new file mode 100644 index 0000000..59a9bcd --- /dev/null +++ b/CarCrimeCity/Part2/cGameSettings.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +extern "C" +{ +#include "lua533/include/lua.h" +#include "lua533/include/lauxlib.h" +#include "lua533/include/lualib.h" +} + +#ifdef _WIN32 + #pragma comment(lib, "lua533/liblua53.a") +#endif + +/* + This is a singleton that stores all the games configuration settings. + These settings are loaded on game start up and are to be considered + read-only. +*/ + +struct sAssetModel +{ + std::string sCreator; + std::string sDescription; + std::string sModelOBJ; + std::string sModelPNG; + float fRotate[3]; + float fScale[3]; + float fTranslate[3]; +}; + +struct sAssetTexture +{ + std::string sName; + std::string sFile; +}; + +class cGameSettings +{ +public: + cGameSettings(); + ~cGameSettings(); + +public: + bool LoadConfigFile(std::string sFile); + +public: + static int nScreenWidth; + static int nScreenHeight; + static int nPixelWidth; + static int nPixelHeight; + static bool bFullScreen; + + static int nDefaultMapWidth; + static int nDefaultMapHeight; + static std::string sDefaultCityFile; + + static std::vector vecAssetTextures; + static std::vector vecAssetBuildings; + static std::vector vecAssetVehicles; +}; + diff --git a/CarCrimeCity/Part2/lua53.dll b/CarCrimeCity/Part2/lua53.dll new file mode 100644 index 0000000..2ab8168 Binary files /dev/null and b/CarCrimeCity/Part2/lua53.dll differ diff --git a/CarCrimeCity/Part2/main.cpp b/CarCrimeCity/Part2/main.cpp new file mode 100644 index 0000000..3568ee2 --- /dev/null +++ b/CarCrimeCity/Part2/main.cpp @@ -0,0 +1,367 @@ +/* + Top Down City Based Car Crime Game - Part #2 + "Colin, I hope you're shooting 600+ wherever you are buddy. RIP." - javidx9 + + License (OLC-3) + ~~~~~~~~~~~~~~~ + + Copyright 2018-2019 OneLoneCoder.com + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions or derivations of source code must retain the above + copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions or derivative works in binary form must reproduce + the above copyright notice. This list of conditions and the following + disclaimer must be reproduced in the documentation and/or other + materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Instructions: + ~~~~~~~~~~~~~ + Scroll with middle mouse wheel, TAB toggle edit mode, R to place road + P to place pavement, Q to place building, Arrow keys to drive car + + Relevant Video: https://youtu.be/fIV6P1W-wuo + + Links + ~~~~~ + YouTube: https://www.youtube.com/javidx9 + https://www.youtube.com/javidx9extra + Discord: https://discord.gg/WhwHUMV + Twitter: https://www.twitter.com/javidx9 + Twitch: https://www.twitch.tv/javidx9 + GitHub: https://www.github.com/onelonecoder + Patreon: https://www.patreon.com/javidx9 + Homepage: https://www.onelonecoder.com + + Author + ~~~~~~ + David Barr, aka javidx9, ©OneLoneCoder 2019 +*/ + + +#include "cGameSettings.h" +#include "cCarCrimeCity.h" + + +int main() +{ + // Load the settings singleton + cGameSettings config; + if (!config.LoadConfigFile("assets/config.lua")) + { + std::cout << "Failed to load '/assets/config.lua'" << std::endl; + std::cout << " -> Using default configuration" << std::endl; + } + + // Start the PixelGameEngine + cCarCrimeCity game; + if (game.Construct(config.nScreenWidth, config.nScreenHeight, config.nPixelWidth, config.nPixelHeight, config.bFullScreen)) + game.Start(); + + // Exit! + return 0; +} + +//#define OLC_PGE_APPLICATION +//#include "olcPixelGameEngine.h" +// +//#define OLC_PGEX_GRAPHICS3D +//#include "olcPGEX_Graphics3D.h" +// +// +// +//enum CELLTYPE +//{ +// CELL_BLANK = 0, +// CELL_GRASS = 1, +// CELL_CONCRETE = 2, +// CELL_WATER = 3, +// CELL_BUILDING = 4, +// CELL_ROAD_H = 5, +// CELL_ROAD_V = 6, +// CELL_ROAD_C1 = 7, +// CELL_ROAD_C2 = 8, +// CELL_ROAD_C3 = 9, +// CELL_ROAD_C4 = 10, +// CELL_ROAD_T1 = 11, +// CELL_ROAD_T2 = 12, +// CELL_ROAD_T3 = 13, +// CELL_ROAD_T4 = 14, +// CELL_ROAD_X = 15, +//}; +// +//struct cCityCell +//{ +// int nType = 5;// CELL_GRASS; +//}; +// +//class cCityMap +//{ +//public: +// // Construct a "blank" city w units wide by h units high +// cCityMap(int w, int h); +// +// // Cleans up city, like Batman +// ~cCityMap(); +// +// +//public: +// // Return width of city in cells +// int GetWidth(); +// // Return height of city in cells +// int GetHeight(); +// // Return a specific cell reference if inside city limits, or nullptr +// cCityCell* Cell(int x, int y); +// +//private: +// int m_nWidth = 0; +// int m_nHeight = 0; +// cCityCell *m_pCells = nullptr; +// +//private: +// // Creates a "default" city of specified size +// void CreateCity(int w, int h); +// // Destroy city +// void ReleaseCity(); +//}; +// +//cCityMap::cCityMap(int w, int h) +//{ +// CreateCity(w, h); +//} +// +//cCityMap::~cCityMap() +//{ +// //ReleaseCity(); +//} +// +//int cCityMap::GetWidth() +//{ +// return m_nWidth; +//} +// +//int cCityMap::GetHeight() +//{ +// return m_nHeight; +//} +// +//cCityCell* cCityMap::Cell(int x, int y) +//{ +// if (x >= 0 && x < m_nWidth && y >= 0 && y < m_nHeight) +// return &m_pCells[y*m_nWidth + x]; +// else +// return nullptr; +//} +// +//void cCityMap::CreateCity(int w, int h) +//{ +// //ReleaseCity(); +// m_nWidth = w; +// m_nHeight = h; +// m_pCells = new cCityCell[m_nHeight * m_nWidth]; +// +// for (int x = 0; x < m_nWidth; x++) +// { +// for (int y = 0; y < m_nHeight; y++) +// { +// //m_pCells[y*m_nWidth + x] = new cCityCell(); +// //Cell(x, y)->bRoad = false; +// //Cell(x, y)->nHeight = 0; +// //Cell(x, y)->nWorldX = x; +// //Cell(x, y)->nWorldY = y; +// Cell(x, y)->nType = CELL_GRASS; +// //Cell(x, y)->bBuilding = false; +// } +// } +//} +// +//void cCityMap::ReleaseCity() +//{ +// if (m_pCells != nullptr) delete m_pCells; +// m_nWidth = 0; +// m_nHeight = 0; +//} +// +// +//class cCarCrimeCity : public olc::PixelGameEngine +//{ +//public: +// cCarCrimeCity() +// { +// sAppName = "Car Crime City"; +// } +// +// ~cCarCrimeCity() +// { +// } +// +// bool OnUserCreate() +// { +// // Initialise PGEX 3D +// olc::GFX3D::ConfigureDisplay(); +// +// // Create Default city +// pCity = new cCityMap(64, 32);// cGameSettings::nDefaultMapWidth, cGameSettings::nDefaultMapHeight); +// +// +// // A simple flat unit quad +// meshQuad.tris = +// { +// { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, olc::RED }, +// { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, olc::RED}, +// }; +// +// +// sprOld = new olc::Sprite("assets/system/grass1.png"); +// +// +// +// SetDrawTarget(nullptr); +// return true; +// } +// +// +// bool OnUserUpdate(float fElapsedTime) +// { +// // User Input +// if (GetKey(olc::Key::W).bHeld) vCamera.y -= 2.0f * fElapsedTime; +// if (GetKey(olc::Key::S).bHeld) vCamera.y += 2.0f * fElapsedTime; +// if (GetKey(olc::Key::A).bHeld) vCamera.x -= 2.0f * fElapsedTime; +// if (GetKey(olc::Key::D).bHeld) vCamera.x += 2.0f * fElapsedTime; +// if (GetKey(olc::Key::Z).bHeld) vCamera.z += 10.0f * fElapsedTime; +// if (GetKey(olc::Key::X).bHeld) vCamera.z -= 10.0f * fElapsedTime; +// +// +// vEye = vCamera; +// +// // Perform Ray casting to calculate visible world extents and mouse position +// olc::GFX3D::vec3d vLookTarget = olc::GFX3D::Math::Vec_Add(vEye, vLookDir); +// olc::GFX3D::mat4x4 matProj = olc::GFX3D::Math::Mat_MakeProjection(90.0f, (float)ScreenHeight() / (float)ScreenWidth(), 0.5f, 1000.0f); +// olc::GFX3D::mat4x4 matView = olc::GFX3D::Math::Mat_PointAt(vEye, vLookTarget, vUp); +// +// +// +// // Render Scene +// Clear(olc::BLUE); +// olc::GFX3D::ClearDepth(); +// +// // Create rendering pipeline +// olc::GFX3D::PipeLine pipe; +// pipe.SetProjection(90.0f, (float)ScreenHeight() / (float)ScreenWidth(), 0.5f, 1000.0f, 0.0f, 0.0f, (float)ScreenWidth(), (float)ScreenHeight()); +// pipe.SetCamera(vEye, vLookTarget, vUp); +// +// +// +// int nStartX = 0; +// int nEndX = pCity->GetWidth(); +// int nStartY = 0; +// int nEndY = pCity->GetHeight(); +// +// // Render Ground, Roads, Walls & Buildings +// for (int x = nStartX; x < nEndX; x++) +// { +// if (x == 15) +// int k = 7; +// +// for (int y = nStartY; y < nEndY; y++) +// { +// +// +// switch (pCity->Cell(x, y)->nType) +// { +// case CELL_GRASS: +// { +// olc::GFX3D::mat4x4 matWorld; +// matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)x, (float)y, 0.0f); +// pipe.SetTransform(matWorld); +// pipe.SetTexture(sprOld); +// //pipe.SetTexture(vecSpriteSystem[0]); +// //pipe.Render(vecMeshSystem[0].tris); +// pipe.Render(meshQuad.tris); +// //pipe.Render(vecMeshSystem[0].tris, olc::GFX3D::RENDER_FLAT); +// break; +// } +// +// +// default: +// { +// olc::GFX3D::mat4x4 matWorld; +// matWorld = olc::GFX3D::Math::Mat_MakeTranslation((float)x, (float)y, 0.0f); +// pipe.SetTransform(matWorld); +// pipe.Render(meshQuad.tris, olc::GFX3D::RENDER_WIRE); +// break; +// } +// } +// +// +// +// +// } +// } +// +// +// +// return true; +// } +// +// bool OnUserDestroy() +// { +// return true; +// } +// +// +//private: +// olc::GFX3D::vec3d vCamera = { 0.0f, 0.0f, -10.0f }; +// olc::GFX3D::vec3d vUp = { 0.0f, 1.0f, 0.0f }; +// olc::GFX3D::vec3d vEye = { 0.0f, 0.0f, -10.0f }; +// olc::GFX3D::vec3d vLookDir = { 0.0f, 0.0f, 1.0f }; +// +// +// +// olc::Sprite *sprOld = nullptr; +// olc::GFX3D::mesh meshQuad; +// +// cCityMap *pCity = nullptr; +// +// +// +//}; +// +//int main() +//{ +// // Load the settings singleton +// /*cGameSettings config; +// if (!config.LoadConfigFile("assets/config.lua")) +// { +// std::cout << "Failed to load '/assets/config.lua'" << std::endl; +// std::cout << " -> Using default configuration" << std::endl; +// }*/ +// +// // Start the PixelGameEngine +// cCarCrimeCity game; +// if (game.Construct(256, 240, 4, 4))// config.nScreenWidth, config.nScreenHeight, config.nPixelWidth, config.nPixelHeight)) +// game.Start(); +// +// // Exit! +// return 0; +//} \ No newline at end of file diff --git a/CarCrimeCity/Part2/olcPGEX_Graphics3D.h b/CarCrimeCity/Part2/olcPGEX_Graphics3D.h new file mode 100644 index 0000000..072cc0d --- /dev/null +++ b/CarCrimeCity/Part2/olcPGEX_Graphics3D.h @@ -0,0 +1,1725 @@ +/* + olcPGEX_Graphics3D.h + + +-------------------------------------------------------------+ + | OneLoneCoder Pixel Game Engine Extension | + | 3D Rendering - v0.3 | + +-------------------------------------------------------------+ + + What is this? + ~~~~~~~~~~~~~ + This is an extension to the olcPixelGameEngine, which provides + support for software rendering 3D graphics. + + NOTE!!! This file is under development and may change! + + Big Thanks to MaGetzUb for finding an OOB error, and joshinils + for pointing out sampling inaccuracy. + + License (OLC-3) + ~~~~~~~~~~~~~~~ + + Copyright 2018-2019 OneLoneCoder.com + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions or derivations of source code must retain the above + copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions or derivative works in binary form must reproduce + the above copyright notice. This list of conditions and the following + disclaimer must be reproduced in the documentation and/or other + materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Links + ~~~~~ + YouTube: https://www.youtube.com/javidx9 + Discord: https://discord.gg/WhwHUMV + Twitter: https://www.twitter.com/javidx9 + Twitch: https://www.twitch.tv/javidx9 + GitHub: https://www.github.com/onelonecoder + Patreon: https://www.patreon.com/javidx9 + Homepage: https://www.onelonecoder.com + + Author + ~~~~~~ + David Barr, aka javidx9, ©OneLoneCoder 2018 +*/ + + +#ifndef OLC_PGEX_GFX3D +#define OLC_PGEX_GFX3D + +#include +#include +#include +#include +#include +#include +#undef min +#undef max + +//#include + +namespace olc +{ + // Container class for Advanced 2D Drawing functions + class GFX3D : public olc::PGEX + { + + public: + + struct vec2d + { + float x = 0; + float y = 0; + float z = 0; + }; + + struct vec3d + { + float x = 0; + float y = 0; + float z = 0; + float w = 1; // Need a 4th term to perform sensible matrix vector multiplication + }; + + struct triangle + { + vec3d p[3]; + vec2d t[3]; + olc::Pixel col[3]; + }; + + struct mat4x4 + { + float m[4][4] = { 0 }; + }; + + struct mesh + { + std::vector tris; + bool LoadOBJFile(std::string sFilename, bool bHasTexture = false); + }; + + /*class MipMap : public olc::Sprite + { + public: + MipMap(); + MipMap(std::string sImageFile); + MipMap(std::string sImageFile, olc::ResourcePack *pack); + MipMap(int32_t w, int32_t h); + ~MipMap(); + + public: + olc::rcode LoadFromFile(std::string sImageFile, olc::ResourcePack *pack = nullptr); + olc::rcode LoadFromPGESprFile(std::string sImageFile, olc::ResourcePack *pack = nullptr); + Pixel Sample(float x, float y, float z); + Pixel SampleBL(float u, float v, float z); + + private: + int GenerateMipLevels(); + std::vector vecMipMaps; + + };*/ + + class Math + { + public: + Math(); + public: + static vec3d Mat_MultiplyVector(mat4x4 &m, vec3d &i); + static mat4x4 Mat_MultiplyMatrix(mat4x4 &m1, mat4x4 &m2); + static mat4x4 Mat_MakeIdentity(); + static mat4x4 Mat_MakeRotationX(float fAngleRad); + static mat4x4 Mat_MakeRotationY(float fAngleRad); + static mat4x4 Mat_MakeRotationZ(float fAngleRad); + static mat4x4 Mat_MakeScale(float x, float y, float z); + static mat4x4 Mat_MakeTranslation(float x, float y, float z); + static mat4x4 Mat_MakeProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar); + static mat4x4 Mat_PointAt(vec3d &pos, vec3d &target, vec3d &up); + static mat4x4 Mat_QuickInverse(mat4x4 &m); // Only for Rotation/Translation Matrices + static mat4x4 Mat_Inverse(olc::GFX3D::mat4x4 &m); + + static vec3d Vec_Add(vec3d &v1, vec3d &v2); + static vec3d Vec_Sub(vec3d &v1, vec3d &v2); + static vec3d Vec_Mul(vec3d &v1, float k); + static vec3d Vec_Div(vec3d &v1, float k); + static float Vec_DotProduct(vec3d &v1, vec3d &v2); + static float Vec_Length(vec3d &v); + static vec3d Vec_Normalise(vec3d &v); + static vec3d Vec_CrossProduct(vec3d &v1, vec3d &v2); + static vec3d Vec_IntersectPlane(vec3d &plane_p, vec3d &plane_n, vec3d &lineStart, vec3d &lineEnd, float &t); + + static int Triangle_ClipAgainstPlane(vec3d plane_p, vec3d plane_n, triangle &in_tri, triangle &out_tri1, triangle &out_tri2); + }; + + enum RENDERFLAGS + { + RENDER_WIRE = 0x01, + RENDER_FLAT = 0x02, + RENDER_TEXTURED = 0x04, + RENDER_CULL_CW = 0x08, + RENDER_CULL_CCW = 0x10, + RENDER_DEPTH = 0x20, + RENDER_LIGHTS = 0x40, + }; + + enum LIGHTS + { + LIGHT_DISABLED, + LIGHT_AMBIENT, + LIGHT_DIRECTIONAL, + LIGHT_POINT + }; + + + class PipeLine + { + public: + PipeLine(); + + public: + void SetProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar, float fLeft, float fTop, float fWidth, float fHeight); + void SetCamera(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &lookat, olc::GFX3D::vec3d &up); + void SetTransform(olc::GFX3D::mat4x4 &transform); + void SetTexture(olc::Sprite *texture); + //void SetMipMapTexture(olc::GFX3D::MipMap *texture); + void SetLightSource(uint32_t nSlot, uint32_t nType, olc::Pixel col, olc::GFX3D::vec3d pos, olc::GFX3D::vec3d dir = { 0.0f, 0.0f, 1.0f }, float fParam = 0.0f); + uint32_t Render(std::vector &triangles, uint32_t flags = RENDER_CULL_CW | RENDER_TEXTURED | RENDER_DEPTH); + uint32_t Render(std::vector &triangles, uint32_t flags, int nOffset, int nCount); + uint32_t RenderLine(olc::GFX3D::vec3d &p1, olc::GFX3D::vec3d &p2, olc::Pixel col = olc::WHITE); + uint32_t RenderCircleXZ(olc::GFX3D::vec3d &p1, float r, olc::Pixel col = olc::WHITE); + + private: + olc::GFX3D::mat4x4 matProj; + olc::GFX3D::mat4x4 matView; + olc::GFX3D::mat4x4 matWorld; + olc::Sprite *sprTexture; + //olc::GFX3D::MipMap *sprMipMap; + //bool bUseMipMap; + float fViewX; + float fViewY; + float fViewW; + float fViewH; + + struct sLight + { + uint32_t type; + olc::GFX3D::vec3d pos; + olc::GFX3D::vec3d dir; + olc::Pixel col; + float param; + } lights[4]; + }; + + + + public: + //static const int RF_TEXTURE = 0x00000001; + //static const int RF_ = 0x00000002; + + static void ConfigureDisplay(); + static void ClearDepth(); + static void AddTriangleToScene(olc::GFX3D::triangle &tri); + static void RenderScene(); + + static void DrawTriangleFlat(olc::GFX3D::triangle &tri); + static void DrawTriangleWire(olc::GFX3D::triangle &tri, olc::Pixel col = olc::WHITE); + static void DrawTriangleTex(olc::GFX3D::triangle &tri, olc::Sprite* spr); + static void TexturedTriangle(int x1, int y1, float u1, float v1, float w1, + int x2, int y2, float u2, float v2, float w2, + int x3, int y3, float u3, float v3, float w3, olc::Sprite* spr); + + static void RasterTriangle(int x1, int y1, float u1, float v1, float w1, olc::Pixel c1, + int x2, int y2, float u2, float v2, float w2, olc::Pixel c2, + int x3, int y3, float u3, float v3, float w3, olc::Pixel c3, + olc::Sprite* spr, + uint32_t nFlags); + + // Draws a sprite with the transform applied + //inline static void DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform); + + private: + static float* m_DepthBuffer; + }; +} + +#endif + + +#ifdef OLC_PGEX_GRAPHICS3D +#undef OLC_PGEX_GRAPHICS3D + +namespace olc +{ + olc::GFX3D::Math::Math() + { + + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Mat_MultiplyVector(olc::GFX3D::mat4x4 &m, olc::GFX3D::vec3d &i) + { + vec3d v; + v.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + i.w * m.m[3][0]; + v.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + i.w * m.m[3][1]; + v.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + i.w * m.m[3][2]; + v.w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + i.w * m.m[3][3]; + return v; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeIdentity() + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = 1.0f; + matrix.m[1][1] = 1.0f; + matrix.m[2][2] = 1.0f; + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationX(float fAngleRad) + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = 1.0f; + matrix.m[1][1] = cosf(fAngleRad); + matrix.m[1][2] = sinf(fAngleRad); + matrix.m[2][1] = -sinf(fAngleRad); + matrix.m[2][2] = cosf(fAngleRad); + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationY(float fAngleRad) + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = cosf(fAngleRad); + matrix.m[0][2] = sinf(fAngleRad); + matrix.m[2][0] = -sinf(fAngleRad); + matrix.m[1][1] = 1.0f; + matrix.m[2][2] = cosf(fAngleRad); + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeRotationZ(float fAngleRad) + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = cosf(fAngleRad); + matrix.m[0][1] = sinf(fAngleRad); + matrix.m[1][0] = -sinf(fAngleRad); + matrix.m[1][1] = cosf(fAngleRad); + matrix.m[2][2] = 1.0f; + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeScale(float x, float y, float z) + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = x; + matrix.m[1][1] = y; + matrix.m[2][2] = z; + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeTranslation(float x, float y, float z) + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = 1.0f; + matrix.m[1][1] = 1.0f; + matrix.m[2][2] = 1.0f; + matrix.m[3][3] = 1.0f; + matrix.m[3][0] = x; + matrix.m[3][1] = y; + matrix.m[3][2] = z; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MakeProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar) + { + float fFovRad = 1.0f / tanf(fFovDegrees * 0.5f / 180.0f * 3.14159f); + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = fAspectRatio * fFovRad; + matrix.m[1][1] = fFovRad; + matrix.m[2][2] = fFar / (fFar - fNear); + matrix.m[3][2] = (-fFar * fNear) / (fFar - fNear); + matrix.m[2][3] = 1.0f; + matrix.m[3][3] = 0.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_MultiplyMatrix(olc::GFX3D::mat4x4 &m1, olc::GFX3D::mat4x4 &m2) + { + olc::GFX3D::mat4x4 matrix; + for (int c = 0; c < 4; c++) + for (int r = 0; r < 4; r++) + matrix.m[r][c] = m1.m[r][0] * m2.m[0][c] + m1.m[r][1] * m2.m[1][c] + m1.m[r][2] * m2.m[2][c] + m1.m[r][3] * m2.m[3][c]; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_PointAt(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &target, olc::GFX3D::vec3d &up) + { + // Calculate new forward direction + olc::GFX3D::vec3d newForward = Vec_Sub(target, pos); + newForward = Vec_Normalise(newForward); + + // Calculate new Up direction + olc::GFX3D::vec3d a = Vec_Mul(newForward, Vec_DotProduct(up, newForward)); + olc::GFX3D::vec3d newUp = Vec_Sub(up, a); + newUp = Vec_Normalise(newUp); + + // New Right direction is easy, its just cross product + olc::GFX3D::vec3d newRight = Vec_CrossProduct(newUp, newForward); + + // Construct Dimensioning and Translation Matrix + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = newRight.x; matrix.m[0][1] = newRight.y; matrix.m[0][2] = newRight.z; matrix.m[0][3] = 0.0f; + matrix.m[1][0] = newUp.x; matrix.m[1][1] = newUp.y; matrix.m[1][2] = newUp.z; matrix.m[1][3] = 0.0f; + matrix.m[2][0] = newForward.x; matrix.m[2][1] = newForward.y; matrix.m[2][2] = newForward.z; matrix.m[2][3] = 0.0f; + matrix.m[3][0] = pos.x; matrix.m[3][1] = pos.y; matrix.m[3][2] = pos.z; matrix.m[3][3] = 1.0f; + return matrix; + + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_QuickInverse(olc::GFX3D::mat4x4 &m) // Only for Rotation/Translation Matrices + { + olc::GFX3D::mat4x4 matrix; + matrix.m[0][0] = m.m[0][0]; matrix.m[0][1] = m.m[1][0]; matrix.m[0][2] = m.m[2][0]; matrix.m[0][3] = 0.0f; + matrix.m[1][0] = m.m[0][1]; matrix.m[1][1] = m.m[1][1]; matrix.m[1][2] = m.m[2][1]; matrix.m[1][3] = 0.0f; + matrix.m[2][0] = m.m[0][2]; matrix.m[2][1] = m.m[1][2]; matrix.m[2][2] = m.m[2][2]; matrix.m[2][3] = 0.0f; + matrix.m[3][0] = -(m.m[3][0] * matrix.m[0][0] + m.m[3][1] * matrix.m[1][0] + m.m[3][2] * matrix.m[2][0]); + matrix.m[3][1] = -(m.m[3][0] * matrix.m[0][1] + m.m[3][1] * matrix.m[1][1] + m.m[3][2] * matrix.m[2][1]); + matrix.m[3][2] = -(m.m[3][0] * matrix.m[0][2] + m.m[3][1] * matrix.m[1][2] + m.m[3][2] * matrix.m[2][2]); + matrix.m[3][3] = 1.0f; + return matrix; + } + + olc::GFX3D::mat4x4 olc::GFX3D::Math::Mat_Inverse(olc::GFX3D::mat4x4 &m) + { + double det; + + + mat4x4 matInv; + + matInv.m[0][0] = m.m[1][1] * m.m[2][2] * m.m[3][3] - m.m[1][1] * m.m[2][3] * m.m[3][2] - m.m[2][1] * m.m[1][2] * m.m[3][3] + m.m[2][1] * m.m[1][3] * m.m[3][2] + m.m[3][1] * m.m[1][2] * m.m[2][3] - m.m[3][1] * m.m[1][3] * m.m[2][2]; + matInv.m[1][0] = -m.m[1][0] * m.m[2][2] * m.m[3][3] + m.m[1][0] * m.m[2][3] * m.m[3][2] + m.m[2][0] * m.m[1][2] * m.m[3][3] - m.m[2][0] * m.m[1][3] * m.m[3][2] - m.m[3][0] * m.m[1][2] * m.m[2][3] + m.m[3][0] * m.m[1][3] * m.m[2][2]; + matInv.m[2][0] = m.m[1][0] * m.m[2][1] * m.m[3][3] - m.m[1][0] * m.m[2][3] * m.m[3][1] - m.m[2][0] * m.m[1][1] * m.m[3][3] + m.m[2][0] * m.m[1][3] * m.m[3][1] + m.m[3][0] * m.m[1][1] * m.m[2][3] - m.m[3][0] * m.m[1][3] * m.m[2][1]; + matInv.m[3][0] = -m.m[1][0] * m.m[2][1] * m.m[3][2] + m.m[1][0] * m.m[2][2] * m.m[3][1] + m.m[2][0] * m.m[1][1] * m.m[3][2] - m.m[2][0] * m.m[1][2] * m.m[3][1] - m.m[3][0] * m.m[1][1] * m.m[2][2] + m.m[3][0] * m.m[1][2] * m.m[2][1]; + matInv.m[0][1] = -m.m[0][1] * m.m[2][2] * m.m[3][3] + m.m[0][1] * m.m[2][3] * m.m[3][2] + m.m[2][1] * m.m[0][2] * m.m[3][3] - m.m[2][1] * m.m[0][3] * m.m[3][2] - m.m[3][1] * m.m[0][2] * m.m[2][3] + m.m[3][1] * m.m[0][3] * m.m[2][2]; + matInv.m[1][1] = m.m[0][0] * m.m[2][2] * m.m[3][3] - m.m[0][0] * m.m[2][3] * m.m[3][2] - m.m[2][0] * m.m[0][2] * m.m[3][3] + m.m[2][0] * m.m[0][3] * m.m[3][2] + m.m[3][0] * m.m[0][2] * m.m[2][3] - m.m[3][0] * m.m[0][3] * m.m[2][2]; + matInv.m[2][1] = -m.m[0][0] * m.m[2][1] * m.m[3][3] + m.m[0][0] * m.m[2][3] * m.m[3][1] + m.m[2][0] * m.m[0][1] * m.m[3][3] - m.m[2][0] * m.m[0][3] * m.m[3][1] - m.m[3][0] * m.m[0][1] * m.m[2][3] + m.m[3][0] * m.m[0][3] * m.m[2][1]; + matInv.m[3][1] = m.m[0][0] * m.m[2][1] * m.m[3][2] - m.m[0][0] * m.m[2][2] * m.m[3][1] - m.m[2][0] * m.m[0][1] * m.m[3][2] + m.m[2][0] * m.m[0][2] * m.m[3][1] + m.m[3][0] * m.m[0][1] * m.m[2][2] - m.m[3][0] * m.m[0][2] * m.m[2][1]; + matInv.m[0][2] = m.m[0][1] * m.m[1][2] * m.m[3][3] - m.m[0][1] * m.m[1][3] * m.m[3][2] - m.m[1][1] * m.m[0][2] * m.m[3][3] + m.m[1][1] * m.m[0][3] * m.m[3][2] + m.m[3][1] * m.m[0][2] * m.m[1][3] - m.m[3][1] * m.m[0][3] * m.m[1][2]; + matInv.m[1][2] = -m.m[0][0] * m.m[1][2] * m.m[3][3] + m.m[0][0] * m.m[1][3] * m.m[3][2] + m.m[1][0] * m.m[0][2] * m.m[3][3] - m.m[1][0] * m.m[0][3] * m.m[3][2] - m.m[3][0] * m.m[0][2] * m.m[1][3] + m.m[3][0] * m.m[0][3] * m.m[1][2]; + matInv.m[2][2] = m.m[0][0] * m.m[1][1] * m.m[3][3] - m.m[0][0] * m.m[1][3] * m.m[3][1] - m.m[1][0] * m.m[0][1] * m.m[3][3] + m.m[1][0] * m.m[0][3] * m.m[3][1] + m.m[3][0] * m.m[0][1] * m.m[1][3] - m.m[3][0] * m.m[0][3] * m.m[1][1]; + matInv.m[3][2] = -m.m[0][0] * m.m[1][1] * m.m[3][2] + m.m[0][0] * m.m[1][2] * m.m[3][1] + m.m[1][0] * m.m[0][1] * m.m[3][2] - m.m[1][0] * m.m[0][2] * m.m[3][1] - m.m[3][0] * m.m[0][1] * m.m[1][2] + m.m[3][0] * m.m[0][2] * m.m[1][1]; + matInv.m[0][3] = -m.m[0][1] * m.m[1][2] * m.m[2][3] + m.m[0][1] * m.m[1][3] * m.m[2][2] + m.m[1][1] * m.m[0][2] * m.m[2][3] - m.m[1][1] * m.m[0][3] * m.m[2][2] - m.m[2][1] * m.m[0][2] * m.m[1][3] + m.m[2][1] * m.m[0][3] * m.m[1][2]; + matInv.m[1][3] = m.m[0][0] * m.m[1][2] * m.m[2][3] - m.m[0][0] * m.m[1][3] * m.m[2][2] - m.m[1][0] * m.m[0][2] * m.m[2][3] + m.m[1][0] * m.m[0][3] * m.m[2][2] + m.m[2][0] * m.m[0][2] * m.m[1][3] - m.m[2][0] * m.m[0][3] * m.m[1][2]; + matInv.m[2][3] = -m.m[0][0] * m.m[1][1] * m.m[2][3] + m.m[0][0] * m.m[1][3] * m.m[2][1] + m.m[1][0] * m.m[0][1] * m.m[2][3] - m.m[1][0] * m.m[0][3] * m.m[2][1] - m.m[2][0] * m.m[0][1] * m.m[1][3] + m.m[2][0] * m.m[0][3] * m.m[1][1]; + matInv.m[3][3] = m.m[0][0] * m.m[1][1] * m.m[2][2] - m.m[0][0] * m.m[1][2] * m.m[2][1] - m.m[1][0] * m.m[0][1] * m.m[2][2] + m.m[1][0] * m.m[0][2] * m.m[2][1] + m.m[2][0] * m.m[0][1] * m.m[1][2] - m.m[2][0] * m.m[0][2] * m.m[1][1]; + + det = m.m[0][0] * matInv.m[0][0] + m.m[0][1] * matInv.m[1][0] + m.m[0][2] * matInv.m[2][0] + m.m[0][3] * matInv.m[3][0]; + // if (det == 0) return false; + + det = 1.0 / det; + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + matInv.m[i][j] *= (float)det; + + return matInv; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Add(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2) + { + return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Sub(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2) + { + return { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Mul(olc::GFX3D::vec3d &v1, float k) + { + return { v1.x * k, v1.y * k, v1.z * k }; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Div(olc::GFX3D::vec3d &v1, float k) + { + return { v1.x / k, v1.y / k, v1.z / k }; + } + + float olc::GFX3D::Math::Vec_DotProduct(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2) + { + return v1.x*v2.x + v1.y*v2.y + v1.z * v2.z; + } + + float olc::GFX3D::Math::Vec_Length(olc::GFX3D::vec3d &v) + { + return sqrtf(Vec_DotProduct(v, v)); + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_Normalise(olc::GFX3D::vec3d &v) + { + float l = Vec_Length(v); + return { v.x / l, v.y / l, v.z / l }; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_CrossProduct(olc::GFX3D::vec3d &v1, olc::GFX3D::vec3d &v2) + { + vec3d v; + v.x = v1.y * v2.z - v1.z * v2.y; + v.y = v1.z * v2.x - v1.x * v2.z; + v.z = v1.x * v2.y - v1.y * v2.x; + return v; + } + + olc::GFX3D::vec3d olc::GFX3D::Math::Vec_IntersectPlane(olc::GFX3D::vec3d &plane_p, olc::GFX3D::vec3d &plane_n, olc::GFX3D::vec3d &lineStart, olc::GFX3D::vec3d &lineEnd, float &t) + { + plane_n = Vec_Normalise(plane_n); + float plane_d = -Vec_DotProduct(plane_n, plane_p); + float ad = Vec_DotProduct(lineStart, plane_n); + float bd = Vec_DotProduct(lineEnd, plane_n); + t = (-plane_d - ad) / (bd - ad); + olc::GFX3D::vec3d lineStartToEnd = Vec_Sub(lineEnd, lineStart); + olc::GFX3D::vec3d lineToIntersect = Vec_Mul(lineStartToEnd, t); + return Vec_Add(lineStart, lineToIntersect); + } + + + int olc::GFX3D::Math::Triangle_ClipAgainstPlane(vec3d plane_p, vec3d plane_n, triangle &in_tri, triangle &out_tri1, triangle &out_tri2) + { + // Make sure plane normal is indeed normal + plane_n = Math::Vec_Normalise(plane_n); + + out_tri1.t[0] = in_tri.t[0]; + out_tri2.t[0] = in_tri.t[0]; + out_tri1.t[1] = in_tri.t[1]; + out_tri2.t[1] = in_tri.t[1]; + out_tri1.t[2] = in_tri.t[2]; + out_tri2.t[2] = in_tri.t[2]; + + // Return signed shortest distance from point to plane, plane normal must be normalised + auto dist = [&](vec3d &p) + { + vec3d n = Math::Vec_Normalise(p); + return (plane_n.x * p.x + plane_n.y * p.y + plane_n.z * p.z - Math::Vec_DotProduct(plane_n, plane_p)); + }; + + // Create two temporary storage arrays to classify points either side of plane + // If distance sign is positive, point lies on "inside" of plane + vec3d* inside_points[3]; int nInsidePointCount = 0; + vec3d* outside_points[3]; int nOutsidePointCount = 0; + vec2d* inside_tex[3]; int nInsideTexCount = 0; + vec2d* outside_tex[3]; int nOutsideTexCount = 0; + + + // Get signed distance of each point in triangle to plane + float d0 = dist(in_tri.p[0]); + float d1 = dist(in_tri.p[1]); + float d2 = dist(in_tri.p[2]); + + if (d0 >= 0) { inside_points[nInsidePointCount++] = &in_tri.p[0]; inside_tex[nInsideTexCount++] = &in_tri.t[0]; } + else { + outside_points[nOutsidePointCount++] = &in_tri.p[0]; outside_tex[nOutsideTexCount++] = &in_tri.t[0]; + } + if (d1 >= 0) { + inside_points[nInsidePointCount++] = &in_tri.p[1]; inside_tex[nInsideTexCount++] = &in_tri.t[1]; + } + else { + outside_points[nOutsidePointCount++] = &in_tri.p[1]; outside_tex[nOutsideTexCount++] = &in_tri.t[1]; + } + if (d2 >= 0) { + inside_points[nInsidePointCount++] = &in_tri.p[2]; inside_tex[nInsideTexCount++] = &in_tri.t[2]; + } + else { + outside_points[nOutsidePointCount++] = &in_tri.p[2]; outside_tex[nOutsideTexCount++] = &in_tri.t[2]; + } + + // Now classify triangle points, and break the input triangle into + // smaller output triangles if required. There are four possible + // outcomes... + + if (nInsidePointCount == 0) + { + // All points lie on the outside of plane, so clip whole triangle + // It ceases to exist + + return 0; // No returned triangles are valid + } + + if (nInsidePointCount == 3) + { + // All points lie on the inside of plane, so do nothing + // and allow the triangle to simply pass through + out_tri1 = in_tri; + + return 1; // Just the one returned original triangle is valid + } + + if (nInsidePointCount == 1 && nOutsidePointCount == 2) + { + // Triangle should be clipped. As two points lie outside + // the plane, the triangle simply becomes a smaller triangle + + // Copy appearance info to new triangle + out_tri1.col[0] = in_tri.col[0]; + out_tri1.col[1] = in_tri.col[1]; + out_tri1.col[2] = in_tri.col[2]; + + // The inside point is valid, so keep that... + out_tri1.p[0] = *inside_points[0]; + out_tri1.t[0] = *inside_tex[0]; + + // but the two new points are at the locations where the + // original sides of the triangle (lines) intersect with the plane + float t; + out_tri1.p[1] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[0], t); + out_tri1.t[1].x = t * (outside_tex[0]->x - inside_tex[0]->x) + inside_tex[0]->x; + out_tri1.t[1].y = t * (outside_tex[0]->y - inside_tex[0]->y) + inside_tex[0]->y; + out_tri1.t[1].z = t * (outside_tex[0]->z - inside_tex[0]->z) + inside_tex[0]->z; + + out_tri1.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[1], t); + out_tri1.t[2].x = t * (outside_tex[1]->x - inside_tex[0]->x) + inside_tex[0]->x; + out_tri1.t[2].y = t * (outside_tex[1]->y - inside_tex[0]->y) + inside_tex[0]->y; + out_tri1.t[2].z = t * (outside_tex[1]->z - inside_tex[0]->z) + inside_tex[0]->z; + + return 1; // Return the newly formed single triangle + } + + if (nInsidePointCount == 2 && nOutsidePointCount == 1) + { + // Triangle should be clipped. As two points lie inside the plane, + // the clipped triangle becomes a "quad". Fortunately, we can + // represent a quad with two new triangles + + // Copy appearance info to new triangles + out_tri1.col[0] = in_tri.col[0]; + out_tri2.col[0] = in_tri.col[0]; + out_tri1.col[1] = in_tri.col[1]; + out_tri2.col[1] = in_tri.col[1]; + out_tri1.col[2] = in_tri.col[2]; + out_tri2.col[2] = in_tri.col[2]; + + // The first triangle consists of the two inside points and a new + // point determined by the location where one side of the triangle + // intersects with the plane + out_tri1.p[0] = *inside_points[0]; + out_tri1.t[0] = *inside_tex[0]; + + out_tri1.p[1] = *inside_points[1]; + out_tri1.t[1] = *inside_tex[1]; + + float t; + out_tri1.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[0], *outside_points[0], t); + out_tri1.t[2].x = t * (outside_tex[0]->x - inside_tex[0]->x) + inside_tex[0]->x; + out_tri1.t[2].y = t * (outside_tex[0]->y - inside_tex[0]->y) + inside_tex[0]->y; + out_tri1.t[2].z = t * (outside_tex[0]->z - inside_tex[0]->z) + inside_tex[0]->z; + + // The second triangle is composed of one of he inside points, a + // new point determined by the intersection of the other side of the + // triangle and the plane, and the newly created point above + out_tri2.p[1] = *inside_points[1]; + out_tri2.t[1] = *inside_tex[1]; + out_tri2.p[0] = out_tri1.p[2]; + out_tri2.t[0] = out_tri1.t[2]; + out_tri2.p[2] = Math::Vec_IntersectPlane(plane_p, plane_n, *inside_points[1], *outside_points[0], t); + out_tri2.t[2].x = t * (outside_tex[0]->x - inside_tex[1]->x) + inside_tex[1]->x; + out_tri2.t[2].y = t * (outside_tex[0]->y - inside_tex[1]->y) + inside_tex[1]->y; + out_tri2.t[2].z = t * (outside_tex[0]->z - inside_tex[1]->z) + inside_tex[1]->z; + return 2; // Return two newly formed triangles which form a quad + } + + return 0; + } + + void GFX3D::DrawTriangleFlat(olc::GFX3D::triangle &tri) + { + pge->FillTriangle(tri.p[0].x, tri.p[0].y, tri.p[1].x, tri.p[1].y, tri.p[2].x, tri.p[2].y, tri.col[0]); + } + + void GFX3D::DrawTriangleWire(olc::GFX3D::triangle &tri, olc::Pixel col) + { + pge->DrawTriangle(tri.p[0].x, tri.p[0].y, tri.p[1].x, tri.p[1].y, tri.p[2].x, tri.p[2].y, col); + } + + void GFX3D::TexturedTriangle(int x1, int y1, float u1, float v1, float w1, + int x2, int y2, float u2, float v2, float w2, + int x3, int y3, float u3, float v3, float w3, olc::Sprite* spr) + + { + if (y2 < y1) + { + std::swap(y1, y2); + std::swap(x1, x2); + std::swap(u1, u2); + std::swap(v1, v2); + std::swap(w1, w2); + } + + if (y3 < y1) + { + std::swap(y1, y3); + std::swap(x1, x3); + std::swap(u1, u3); + std::swap(v1, v3); + std::swap(w1, w3); + } + + if (y3 < y2) + { + std::swap(y2, y3); + std::swap(x2, x3); + std::swap(u2, u3); + std::swap(v2, v3); + std::swap(w2, w3); + } + + int dy1 = y2 - y1; + int dx1 = x2 - x1; + float dv1 = v2 - v1; + float du1 = u2 - u1; + float dw1 = w2 - w1; + + int dy2 = y3 - y1; + int dx2 = x3 - x1; + float dv2 = v3 - v1; + float du2 = u3 - u1; + float dw2 = w3 - w1; + + float tex_u, tex_v, tex_w; + + float dax_step = 0, dbx_step = 0, + du1_step = 0, dv1_step = 0, + du2_step = 0, dv2_step = 0, + dw1_step = 0, dw2_step = 0; + + if (dy1) dax_step = dx1 / (float)abs(dy1); + if (dy2) dbx_step = dx2 / (float)abs(dy2); + + if (dy1) du1_step = du1 / (float)abs(dy1); + if (dy1) dv1_step = dv1 / (float)abs(dy1); + if (dy1) dw1_step = dw1 / (float)abs(dy1); + + if (dy2) du2_step = du2 / (float)abs(dy2); + if (dy2) dv2_step = dv2 / (float)abs(dy2); + if (dy2) dw2_step = dw2 / (float)abs(dy2); + + if (dy1) + { + for (int i = y1; i <= y2; i++) + { + int ax = x1 + (float)(i - y1) * dax_step; + int bx = x1 + (float)(i - y1) * dbx_step; + + float tex_su = u1 + (float)(i - y1) * du1_step; + float tex_sv = v1 + (float)(i - y1) * dv1_step; + float tex_sw = w1 + (float)(i - y1) * dw1_step; + + float tex_eu = u1 + (float)(i - y1) * du2_step; + float tex_ev = v1 + (float)(i - y1) * dv2_step; + float tex_ew = w1 + (float)(i - y1) * dw2_step; + + if (ax > bx) + { + std::swap(ax, bx); + std::swap(tex_su, tex_eu); + std::swap(tex_sv, tex_ev); + std::swap(tex_sw, tex_ew); + } + + tex_u = tex_su; + tex_v = tex_sv; + tex_w = tex_sw; + + float tstep = 1.0f / ((float)(bx - ax)); + float t = 0.0f; + + for (int j = ax; j < bx; j++) + { + tex_u = (1.0f - t) * tex_su + t * tex_eu; + tex_v = (1.0f - t) * tex_sv + t * tex_ev; + tex_w = (1.0f - t) * tex_sw + t * tex_ew; + if (tex_w > m_DepthBuffer[i*pge->ScreenWidth() + j]) + { + /*if (bMipMap) + pge->Draw(j, i, ((olc::GFX3D::MipMap*)spr)->Sample(tex_u / tex_w, tex_v / tex_w, tex_w)); + else*/ + if(pge->Draw(j, i, spr != nullptr ? spr->Sample(tex_u / tex_w, tex_v / tex_w) : olc::GREY)) + m_DepthBuffer[i*pge->ScreenWidth() + j] = tex_w; + } + t += tstep; + } + + } + } + + dy1 = y3 - y2; + dx1 = x3 - x2; + dv1 = v3 - v2; + du1 = u3 - u2; + dw1 = w3 - w2; + + if (dy1) dax_step = dx1 / (float)abs(dy1); + if (dy2) dbx_step = dx2 / (float)abs(dy2); + + du1_step = 0, dv1_step = 0; + if (dy1) du1_step = du1 / (float)abs(dy1); + if (dy1) dv1_step = dv1 / (float)abs(dy1); + if (dy1) dw1_step = dw1 / (float)abs(dy1); + + if (dy1) + { + for (int i = y2; i <= y3; i++) + { + int ax = x2 + (float)(i - y2) * dax_step; + int bx = x1 + (float)(i - y1) * dbx_step; + + float tex_su = u2 + (float)(i - y2) * du1_step; + float tex_sv = v2 + (float)(i - y2) * dv1_step; + float tex_sw = w2 + (float)(i - y2) * dw1_step; + + float tex_eu = u1 + (float)(i - y1) * du2_step; + float tex_ev = v1 + (float)(i - y1) * dv2_step; + float tex_ew = w1 + (float)(i - y1) * dw2_step; + + if (ax > bx) + { + std::swap(ax, bx); + std::swap(tex_su, tex_eu); + std::swap(tex_sv, tex_ev); + std::swap(tex_sw, tex_ew); + } + + tex_u = tex_su; + tex_v = tex_sv; + tex_w = tex_sw; + + float tstep = 1.0f / ((float)(bx - ax)); + float t = 0.0f; + + for (int j = ax; j < bx; j++) + { + tex_u = (1.0f - t) * tex_su + t * tex_eu; + tex_v = (1.0f - t) * tex_sv + t * tex_ev; + tex_w = (1.0f - t) * tex_sw + t * tex_ew; + + if (tex_w > m_DepthBuffer[i*pge->ScreenWidth() + j]) + { + /*if(bMipMap) + pge->Draw(j, i, ((olc::GFX3D::MipMap*)spr)->Sample(tex_u / tex_w, tex_v / tex_w, tex_w)); + else*/ + if(pge->Draw(j, i, spr != nullptr ? spr->Sample(tex_u / tex_w, tex_v / tex_w) : olc::GREY)) + m_DepthBuffer[i*pge->ScreenWidth() + j] = tex_w; + } + t += tstep; + } + } + } + } + + + void GFX3D::DrawTriangleTex(olc::GFX3D::triangle &tri, olc::Sprite* spr) + { + + } + + float* GFX3D::m_DepthBuffer = nullptr; + + void GFX3D::ConfigureDisplay() + { + m_DepthBuffer = new float[pge->ScreenWidth() * pge->ScreenHeight()]{ 0 }; + } + + + void GFX3D::ClearDepth() + { + memset(m_DepthBuffer, 0, pge->ScreenWidth() * pge->ScreenHeight() * sizeof(float)); + } + + bool GFX3D::mesh::LoadOBJFile(std::string sFilename, bool bHasTexture) + { + std::ifstream f(sFilename); + if (!f.is_open()) return false; + + // Local cache of verts + std::vector verts; + std::vector norms; + std::vector texs; + + while (!f.eof()) + { + char line[128]; + f.getline(line, 128); + + std::strstream s; + s << line; + + char junk; + + if (line[0] == 'v') + { + if (line[1] == 't') + { + vec2d v; + s >> junk >> junk >> v.x >> v.y; + //v.x = 1.0f - v.x; + v.y = 1.0f - v.y; + texs.push_back(v); + } + else if (line[1] == 'n') + { + vec3d v; + s >> junk >> junk >> v.x >> v.y >> v.z; + norms.push_back(v); + } + else + { + vec3d v; + s >> junk >> v.x >> v.y >> v.z; + verts.push_back(v); + } + } + + + /*if (!bHasTexture) + { + if (line[0] == 'f') + { + int f[3]; + s >> junk >> f[0] >> f[1] >> f[2]; + tris.push_back({ verts[f[0] - 1], verts[f[1] - 1], verts[f[2] - 1] }); + } + } + else*/ + { + if (line[0] == 'f') + { + s >> junk; + + std::string tokens[9]; + int nTokenCount = -1; + while (!s.eof()) + { + char c = s.get(); + if (c == ' ' || c == '/') + { + if (tokens[nTokenCount].size() > 0) + { + nTokenCount++; + } + } + else + tokens[nTokenCount].append(1, c); + } + + tokens[nTokenCount].pop_back(); + + int stride = 1; + if (!texs.empty()) stride++; + if (!norms.empty()) stride++; + + if (!texs.empty()) + { + tris.push_back({ + verts[stoi(tokens[0 * stride]) - 1], + verts[stoi(tokens[1 * stride]) - 1], + verts[stoi(tokens[2 * stride]) - 1], + texs[stoi(tokens[0 * stride + 1]) - 1], + texs[stoi(tokens[1 * stride + 1]) - 1], + texs[stoi(tokens[2 * stride + 1]) - 1], + olc::WHITE, olc::WHITE, olc::WHITE}); + } + else + { + tris.push_back({ + verts[stoi(tokens[0 * stride]) - 1], + verts[stoi(tokens[1 * stride]) - 1], + verts[stoi(tokens[2 * stride]) - 1], + olc::GFX3D::vec2d{0,0,0}, + olc::GFX3D::vec2d{0,0,0}, + olc::GFX3D::vec2d{0,0,0}, + olc::WHITE, olc::WHITE, olc::WHITE }); + + } + } + } + } + return true; + } + + + GFX3D::PipeLine::PipeLine() + { + //bUseMipMap = false; + } + + void GFX3D::PipeLine::SetProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar, float fLeft, float fTop, float fWidth, float fHeight) + { + matProj = GFX3D::Math::Mat_MakeProjection(fFovDegrees, fAspectRatio, fNear, fFar); + fViewX = fLeft; + fViewY = fTop; + fViewW = fWidth; + fViewH = fHeight; + } + + void GFX3D::PipeLine::SetCamera(olc::GFX3D::vec3d &pos, olc::GFX3D::vec3d &lookat, olc::GFX3D::vec3d &up) + { + matView = GFX3D::Math::Mat_PointAt(pos, lookat, up); + matView = GFX3D::Math::Mat_QuickInverse(matView); + } + + void GFX3D::PipeLine::SetTransform(olc::GFX3D::mat4x4 &transform) + { + matWorld = transform; + } + + void GFX3D::PipeLine::SetTexture(olc::Sprite *texture) + { + sprTexture = texture; + //bUseMipMap = false; + } + + /*void GFX3D::PipeLine::SetMipMapTexture(olc::GFX3D::MipMap *texture) + { + sprMipMap = texture; + bUseMipMap = true; + }*/ + + void GFX3D::PipeLine::SetLightSource(uint32_t nSlot, uint32_t nType, olc::Pixel col, olc::GFX3D::vec3d pos, olc::GFX3D::vec3d dir, float fParam) + { + if (nSlot < 4) + { + lights[nSlot].type = nType; + lights[nSlot].pos = pos; + lights[nSlot].dir = dir; + lights[nSlot].col = col; + lights[nSlot].param = fParam; + } + } + + uint32_t GFX3D::PipeLine::Render(std::vector &triangles, uint32_t flags) + { + return Render(triangles, flags, 0, triangles.size()); + } + + uint32_t GFX3D::PipeLine::RenderLine(olc::GFX3D::vec3d &p1, olc::GFX3D::vec3d &p2, olc::Pixel col) + { + // Coordinates are assumed to be in world space + olc::GFX3D::vec3d t1, t2; + + // Transform into view + t1 = GFX3D::Math::Mat_MultiplyVector(matView, p1); + t2 = GFX3D::Math::Mat_MultiplyVector(matView, p2); + + // Project onto screen + t1 = GFX3D::Math::Mat_MultiplyVector(matProj, t1); + t2 = GFX3D::Math::Mat_MultiplyVector(matProj, t2); + + // Project + t1.x = t1.x / t1.w; + t1.y = t1.y / t1.w; + t1.z = t1.z / t1.w; + + t2.x = t2.x / t2.w; + t2.y = t2.y / t2.w; + t2.z = t2.z / t2.w; + + vec3d vOffsetView = { 1,1,0 }; + t1 = Math::Vec_Add(t1, vOffsetView); + t2 = Math::Vec_Add(t2, vOffsetView); + + t1.x *= 0.5f * fViewW; + t1.y *= 0.5f * fViewH; + t2.x *= 0.5f * fViewW; + t2.y *= 0.5f * fViewH; + + vOffsetView = { fViewX,fViewY,0 }; + t1 = Math::Vec_Add(t1, vOffsetView); + t2 = Math::Vec_Add(t2, vOffsetView); + + pge->DrawLine(t1.x, t1.y, t2.x, t2.y, col); + + return 0; + } + + uint32_t GFX3D::PipeLine::RenderCircleXZ(olc::GFX3D::vec3d &p1, float r, olc::Pixel col) + { + // Coordinates are assumed to be in world space + olc::GFX3D::vec3d t1; + olc::GFX3D::vec3d t2 = { p1.x + r, p1.y, p1.z }; + + // Transform into view + t1 = GFX3D::Math::Mat_MultiplyVector(matView, p1); + t2 = GFX3D::Math::Mat_MultiplyVector(matView, t2); + + // Project onto screen + t1 = GFX3D::Math::Mat_MultiplyVector(matProj, t1); + t2 = GFX3D::Math::Mat_MultiplyVector(matProj, t2); + + // Project + t1.x = t1.x / t1.w; + t1.y = t1.y / t1.w; + t1.z = t1.z / t1.w; + + t2.x = t2.x / t2.w; + t2.y = t2.y / t2.w; + t2.z = t2.z / t2.w; + + vec3d vOffsetView = { 1,1,0 }; + t1 = Math::Vec_Add(t1, vOffsetView); + t2 = Math::Vec_Add(t2, vOffsetView); + + t1.x *= 0.5f * fViewW; + t1.y *= 0.5f * fViewH; + t2.x *= 0.5f * fViewW; + t2.y *= 0.5f * fViewH; + + vOffsetView = { fViewX,fViewY,0 }; + t1 = Math::Vec_Add(t1, vOffsetView); + t2 = Math::Vec_Add(t2, vOffsetView); + + pge->FillCircle(t1.x, t1.y, fabs(t2.x - t1.x), col); + + return 0; + } + + uint32_t GFX3D::PipeLine::Render(std::vector &triangles, uint32_t flags, int nOffset, int nCount) + { + // Calculate Transformation Matrix + mat4x4 matWorldView = Math::Mat_MultiplyMatrix(matWorld, matView); + //matWorldViewProj = Math::Mat_MultiplyMatrix(matWorldView, matProj); + + // Store triangles for rastering later + std::vector vecTrianglesToRaster; + + int nTriangleDrawnCount = 0; + + // Process Triangles + //for (auto &tri : triangles) +// omp_set_dynamic(0); +// omp_set_num_threads(4); +//#pragma omp parallel for schedule(static) + for(int tx = nOffset; tx < nOffset+nCount; tx++) + { + GFX3D::triangle &tri = triangles[tx]; + GFX3D::triangle triTransformed; + + // Just copy through texture coordinates + triTransformed.t[0] = { tri.t[0].x, tri.t[0].y, tri.t[0].z }; + triTransformed.t[1] = { tri.t[1].x, tri.t[1].y, tri.t[1].z }; + triTransformed.t[2] = { tri.t[2].x, tri.t[2].y, tri.t[2].z }; // Think! + + // Dont forget vertex colours + triTransformed.col[0] = tri.col[0]; + triTransformed.col[1] = tri.col[1]; + triTransformed.col[2] = tri.col[2]; + + // Transform Triangle from object into projected space + triTransformed.p[0] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[0]); + triTransformed.p[1] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[1]); + triTransformed.p[2] = GFX3D::Math::Mat_MultiplyVector(matWorldView, tri.p[2]); + + // Calculate Triangle Normal in WorldView Space + GFX3D::vec3d normal, line1, line2; + line1 = GFX3D::Math::Vec_Sub(triTransformed.p[1], triTransformed.p[0]); + line2 = GFX3D::Math::Vec_Sub(triTransformed.p[2], triTransformed.p[0]); + normal = GFX3D::Math::Vec_CrossProduct(line1, line2); + normal = GFX3D::Math::Vec_Normalise(normal); + + // Cull triangles that face away from viewer + if (flags & RENDER_CULL_CW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) > 0.0f) continue; + if (flags & RENDER_CULL_CCW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) < 0.0f) continue; + + // If Lighting, calculate shading + if (flags & RENDER_LIGHTS) + { + olc::Pixel ambient_clamp = { 0,0,0 }; + olc::Pixel light_combined = { 0,0,0 }; + uint32_t nLightSources = 0; + float nLightR = 0, nLightG = 0, nLightB = 0; + + for (int i = 0; i < 4; i++) + { + switch (lights[i].type) + { + case LIGHT_DISABLED: + break; + case LIGHT_AMBIENT: + ambient_clamp = lights[i].col; + break; + case LIGHT_DIRECTIONAL: + { + nLightSources++; + GFX3D::vec3d light_dir = GFX3D::Math::Vec_Normalise(lights[i].dir); + float light = GFX3D::Math::Vec_DotProduct(light_dir, normal); + if (light > 0) + { + int j = 0; + } + + light = std::max(light, 0.0f); + nLightR += light * (lights[i].col.r/255.0f); + nLightG += light * (lights[i].col.g/255.0f); + nLightB += light * (lights[i].col.b/255.0f); + } + break; + case LIGHT_POINT: + break; + } + } + + //nLightR /= nLightSources; + //nLightG /= nLightSources; + //nLightB /= nLightSources; + + nLightR = std::max(nLightR, ambient_clamp.r / 255.0f); + nLightG = std::max(nLightG, ambient_clamp.g / 255.0f); + nLightB = std::max(nLightB, ambient_clamp.b / 255.0f); + + triTransformed.col[0] = olc::Pixel(nLightR * triTransformed.col[0].r, nLightG * triTransformed.col[0].g, nLightB * triTransformed.col[0].b); + triTransformed.col[1] = olc::Pixel(nLightR * triTransformed.col[1].r, nLightG * triTransformed.col[1].g, nLightB * triTransformed.col[1].b); + triTransformed.col[2] = olc::Pixel(nLightR * triTransformed.col[2].r, nLightG * triTransformed.col[2].g, nLightB * triTransformed.col[2].b); + + + + /*GFX3D::vec3d light_dir = { 1,1,1 }; + light_dir = GFX3D::Math::Vec_Normalise(light_dir); + float light = GFX3D::Math::Vec_DotProduct(light_dir, normal); + if (light < 0) light = 0; + triTransformed.col[0] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f); + triTransformed.col[1] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f); + triTransformed.col[2] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f);*/ + } + //else + // triTransformed.col = olc::WHITE; + + // Clip triangle against near plane + int nClippedTriangles = 0; + GFX3D::triangle clipped[2]; + nClippedTriangles = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, 0.0f, 0.1f }, { 0.0f, 0.0f, 1.0f }, triTransformed, clipped[0], clipped[1]); + + // This may yield two new triangles + for (int n = 0; n < nClippedTriangles; n++) + { + triangle triProjected = clipped[n]; + + // Project new triangle + triProjected.p[0] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[0]); + triProjected.p[1] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[1]); + triProjected.p[2] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[2]); + + // Apply Projection to Verts + triProjected.p[0].x = triProjected.p[0].x / triProjected.p[0].w; + triProjected.p[1].x = triProjected.p[1].x / triProjected.p[1].w; + triProjected.p[2].x = triProjected.p[2].x / triProjected.p[2].w; + + triProjected.p[0].y = triProjected.p[0].y / triProjected.p[0].w; + triProjected.p[1].y = triProjected.p[1].y / triProjected.p[1].w; + triProjected.p[2].y = triProjected.p[2].y / triProjected.p[2].w; + + triProjected.p[0].z = triProjected.p[0].z / triProjected.p[0].w; + triProjected.p[1].z = triProjected.p[1].z / triProjected.p[1].w; + triProjected.p[2].z = triProjected.p[2].z / triProjected.p[2].w; + + // Apply Projection to Tex coords + triProjected.t[0].x = triProjected.t[0].x / triProjected.p[0].w; + triProjected.t[1].x = triProjected.t[1].x / triProjected.p[1].w; + triProjected.t[2].x = triProjected.t[2].x / triProjected.p[2].w; + + triProjected.t[0].y = triProjected.t[0].y / triProjected.p[0].w; + triProjected.t[1].y = triProjected.t[1].y / triProjected.p[1].w; + triProjected.t[2].y = triProjected.t[2].y / triProjected.p[2].w; + + triProjected.t[0].z = 1.0f / triProjected.p[0].w; + triProjected.t[1].z = 1.0f / triProjected.p[1].w; + triProjected.t[2].z = 1.0f / triProjected.p[2].w; + + // Clip against viewport in screen space + // Clip triangles against all four screen edges, this could yield + // a bunch of triangles, so create a queue that we traverse to + // ensure we only test new triangles generated against planes + GFX3D::triangle sclipped[2]; + std::list listTriangles; + + + // Add initial triangle + listTriangles.push_back(triProjected); + int nNewTriangles = 1; + + for (int p = 0; p < 4; p++) + { + int nTrisToAdd = 0; + while (nNewTriangles > 0) + { + // Take triangle from front of queue + triangle test = listTriangles.front(); + listTriangles.pop_front(); + nNewTriangles--; + + // Clip it against a plane. We only need to test each + // subsequent plane, against subsequent new triangles + // as all triangles after a plane clip are guaranteed + // to lie on the inside of the plane. I like how this + // comment is almost completely and utterly justified + switch (p) + { + case 0: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, -1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break; + case 1: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, +1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break; + case 2: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break; + case 3: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ +1.0f, 0.0f, 0.0f }, { -1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break; + } + + + // Clipping may yield a variable number of triangles, so + // add these new ones to the back of the queue for subsequent + // clipping against next planes + for (int w = 0; w < nTrisToAdd; w++) + listTriangles.push_back(sclipped[w]); + } + nNewTriangles = listTriangles.size(); + } + + for (auto &triRaster : listTriangles) + { + // Scale to viewport + /*triRaster.p[0].x *= -1.0f; + triRaster.p[1].x *= -1.0f; + triRaster.p[2].x *= -1.0f; + triRaster.p[0].y *= -1.0f; + triRaster.p[1].y *= -1.0f; + triRaster.p[2].y *= -1.0f;*/ + vec3d vOffsetView = { 1,1,0 }; + triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView); + triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView); + triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView); + triRaster.p[0].x *= 0.5f * fViewW; + triRaster.p[0].y *= 0.5f * fViewH; + triRaster.p[1].x *= 0.5f * fViewW; + triRaster.p[1].y *= 0.5f * fViewH; + triRaster.p[2].x *= 0.5f * fViewW; + triRaster.p[2].y *= 0.5f * fViewH; + vOffsetView = { fViewX,fViewY,0 }; + triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView); + triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView); + triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView); + + // For now, just draw triangle + + //if (flags & RENDER_TEXTURED) + //{/* + // TexturedTriangle( + // triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z, + // triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z, + // triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z, + // sprTexture);*/ + + // RasterTriangle( + // triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z, triRaster.col, + // triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z, triRaster.col, + // triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z, triRaster.col, + // sprTexture, nFlags); + + //} + + if (flags & RENDER_WIRE) + { + DrawTriangleWire(triRaster, olc::RED); + } + else + { + RasterTriangle( + triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z, triRaster.col[0], + triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z, triRaster.col[1], + triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z, triRaster.col[2], + sprTexture, flags); + + } + + + + + nTriangleDrawnCount++; + } + } + } + + return nTriangleDrawnCount; + } + + void GFX3D::RasterTriangle(int x1, int y1, float u1, float v1, float w1, olc::Pixel c1, + int x2, int y2, float u2, float v2, float w2, olc::Pixel c2, + int x3, int y3, float u3, float v3, float w3, olc::Pixel c3, + olc::Sprite* spr, + uint32_t nFlags) + + { + if (y2 < y1) + { + std::swap(y1, y2); std::swap(x1, x2); std::swap(u1, u2); std::swap(v1, v2); std::swap(w1, w2); std::swap(c1, c2); + } + + if (y3 < y1) + { + std::swap(y1, y3); std::swap(x1, x3); std::swap(u1, u3); std::swap(v1, v3); std::swap(w1, w3); std::swap(c1, c3); + } + + if (y3 < y2) + { + std::swap(y2, y3); std::swap(x2, x3); std::swap(u2, u3); std::swap(v2, v3); std::swap(w2, w3); std::swap(c2, c3); + } + + int dy1 = y2 - y1; + int dx1 = x2 - x1; + float dv1 = v2 - v1; + float du1 = u2 - u1; + float dw1 = w2 - w1; + int dcr1 = c2.r - c1.r; + int dcg1 = c2.g - c1.g; + int dcb1 = c2.b - c1.b; + int dca1 = c2.a - c1.a; + + int dy2 = y3 - y1; + int dx2 = x3 - x1; + float dv2 = v3 - v1; + float du2 = u3 - u1; + float dw2 = w3 - w1; + int dcr2 = c3.r - c1.r; + int dcg2 = c3.g - c1.g; + int dcb2 = c3.b - c1.b; + int dca2 = c3.a - c1.a; + + float tex_u, tex_v, tex_w; + float col_r, col_g, col_b, col_a; + + float dax_step = 0, dbx_step = 0, + du1_step = 0, dv1_step = 0, + du2_step = 0, dv2_step = 0, + dw1_step = 0, dw2_step = 0, + dcr1_step = 0, dcr2_step = 0, + dcg1_step = 0, dcg2_step = 0, + dcb1_step = 0, dcb2_step = 0, + dca1_step = 0, dca2_step = 0; + + if (dy1) dax_step = dx1 / (float)abs(dy1); + if (dy2) dbx_step = dx2 / (float)abs(dy2); + + if (dy1) du1_step = du1 / (float)abs(dy1); + if (dy1) dv1_step = dv1 / (float)abs(dy1); + if (dy1) dw1_step = dw1 / (float)abs(dy1); + + if (dy2) du2_step = du2 / (float)abs(dy2); + if (dy2) dv2_step = dv2 / (float)abs(dy2); + if (dy2) dw2_step = dw2 / (float)abs(dy2); + + if (dy1) dcr1_step = dcr1 / (float)abs(dy1); + if (dy1) dcg1_step = dcg1 / (float)abs(dy1); + if (dy1) dcb1_step = dcb1 / (float)abs(dy1); + if (dy1) dca1_step = dca1 / (float)abs(dy1); + + if (dy2) dcr2_step = dcr2 / (float)abs(dy2); + if (dy2) dcg2_step = dcg2 / (float)abs(dy2); + if (dy2) dcb2_step = dcb2 / (float)abs(dy2); + if (dy2) dca2_step = dca2 / (float)abs(dy2); + + float pixel_r = 0.0f; + float pixel_g = 0.0f; + float pixel_b = 0.0f; + float pixel_a = 1.0f; + + if (dy1) + { + for (int i = y1; i <= y2; i++) + { + int ax = x1 + (float)(i - y1) * dax_step; + int bx = x1 + (float)(i - y1) * dbx_step; + + float tex_su = u1 + (float)(i - y1) * du1_step; + float tex_sv = v1 + (float)(i - y1) * dv1_step; + float tex_sw = w1 + (float)(i - y1) * dw1_step; + + float tex_eu = u1 + (float)(i - y1) * du2_step; + float tex_ev = v1 + (float)(i - y1) * dv2_step; + float tex_ew = w1 + (float)(i - y1) * dw2_step; + + float col_sr = c1.r + (float)(i - y1) * dcr1_step; + float col_sg = c1.g + (float)(i - y1) * dcg1_step; + float col_sb = c1.b + (float)(i - y1) * dcb1_step; + float col_sa = c1.a + (float)(i - y1) * dca1_step; + + float col_er = c1.r + (float)(i - y1) * dcr2_step; + float col_eg = c1.g + (float)(i - y1) * dcg2_step; + float col_eb = c1.b + (float)(i - y1) * dcb2_step; + float col_ea = c1.a + (float)(i - y1) * dca2_step; + + if (ax > bx) + { + std::swap(ax, bx); + std::swap(tex_su, tex_eu); + std::swap(tex_sv, tex_ev); + std::swap(tex_sw, tex_ew); + std::swap(col_sr, col_er); + std::swap(col_sg, col_eg); + std::swap(col_sb, col_eb); + std::swap(col_sa, col_ea); + } + + tex_u = tex_su; + tex_v = tex_sv; + tex_w = tex_sw; + col_r = col_sr; + col_g = col_sg; + col_b = col_sb; + col_a = col_sa; + + float tstep = 1.0f / ((float)(bx - ax)); + float t = 0.0f; + + for (int j = ax; j < bx; j++) + { + tex_u = (1.0f - t) * tex_su + t * tex_eu; + tex_v = (1.0f - t) * tex_sv + t * tex_ev; + tex_w = (1.0f - t) * tex_sw + t * tex_ew; + col_r = (1.0f - t) * col_sr + t * col_er; + col_g = (1.0f - t) * col_sg + t * col_eg; + col_b = (1.0f - t) * col_sb + t * col_eb; + col_a = (1.0f - t) * col_sa + t * col_ea; + + pixel_r = col_r; + pixel_g = col_g; + pixel_b = col_b; + pixel_a = col_a; + + if (nFlags & GFX3D::RENDER_TEXTURED) + { + if (spr != nullptr) + { + olc::Pixel sample = spr->Sample(tex_u / tex_w, tex_v / tex_w); + pixel_r *= sample.r / 255.0f; + pixel_g *= sample.g / 255.0f; + pixel_b *= sample.b / 255.0f; + pixel_a *= sample.a / 255.0f; + } + } + + if (nFlags & GFX3D::RENDER_DEPTH) + { + if (tex_w > m_DepthBuffer[i*pge->ScreenWidth() + j]) + if (pge->Draw(j, i, olc::Pixel(pixel_r * 1.0f, pixel_g * 1.0f, pixel_b * 1.0f, pixel_a * 1.0f))) + m_DepthBuffer[i*pge->ScreenWidth() + j] = tex_w; + } + else + { + pge->Draw(j, i, olc::Pixel(pixel_r * 1.0f, pixel_g * 1.0f, pixel_b * 1.0f, pixel_a * 1.0f)); + } + + t += tstep; + } + } + } + + dy1 = y3 - y2; + dx1 = x3 - x2; + dv1 = v3 - v2; + du1 = u3 - u2; + dw1 = w3 - w2; + dcr1 = c3.r - c2.r; + dcg1 = c3.g - c2.g; + dcb1 = c3.b - c2.b; + dca1 = c3.a - c2.a; + + if (dy1) dax_step = dx1 / (float)abs(dy1); + if (dy2) dbx_step = dx2 / (float)abs(dy2); + + du1_step = 0; dv1_step = 0; + if (dy1) du1_step = du1 / (float)abs(dy1); + if (dy1) dv1_step = dv1 / (float)abs(dy1); + if (dy1) dw1_step = dw1 / (float)abs(dy1); + + dcr1_step = 0; dcg1_step = 0; dcb1_step = 0; dca1_step = 0; + if (dy1) dcr1_step = dcr1 / (float)abs(dy1); + if (dy1) dcg1_step = dcg1 / (float)abs(dy1); + if (dy1) dcb1_step = dcb1 / (float)abs(dy1); + if (dy1) dca1_step = dca1 / (float)abs(dy1); + + if (dy1) + { + for (int i = y2; i <= y3; i++) + { + int ax = x2 + (float)(i - y2) * dax_step; + int bx = x1 + (float)(i - y1) * dbx_step; + + float tex_su = u2 + (float)(i - y2) * du1_step; + float tex_sv = v2 + (float)(i - y2) * dv1_step; + float tex_sw = w2 + (float)(i - y2) * dw1_step; + + float tex_eu = u1 + (float)(i - y1) * du2_step; + float tex_ev = v1 + (float)(i - y1) * dv2_step; + float tex_ew = w1 + (float)(i - y1) * dw2_step; + + float col_sr = c2.r + (float)(i - y2) * dcr1_step; + float col_sg = c2.g + (float)(i - y2) * dcg1_step; + float col_sb = c2.b + (float)(i - y2) * dcb1_step; + float col_sa = c2.a + (float)(i - y2) * dca1_step; + + float col_er = c1.r + (float)(i - y1) * dcr2_step; + float col_eg = c1.g + (float)(i - y1) * dcg2_step; + float col_eb = c1.b + (float)(i - y1) * dcb2_step; + float col_ea = c1.a + (float)(i - y1) * dca2_step; + + if (ax > bx) + { + std::swap(ax, bx); + std::swap(tex_su, tex_eu); + std::swap(tex_sv, tex_ev); + std::swap(tex_sw, tex_ew); + std::swap(col_sr, col_er); + std::swap(col_sg, col_eg); + std::swap(col_sb, col_eb); + std::swap(col_sa, col_ea); + } + + tex_u = tex_su; + tex_v = tex_sv; + tex_w = tex_sw; + col_r = col_sr; + col_g = col_sg; + col_b = col_sb; + col_a = col_sa; + + float tstep = 1.0f / ((float)(bx - ax)); + float t = 0.0f; + + for (int j = ax; j < bx; j++) + { + tex_u = (1.0f - t) * tex_su + t * tex_eu; + tex_v = (1.0f - t) * tex_sv + t * tex_ev; + tex_w = (1.0f - t) * tex_sw + t * tex_ew; + col_r = (1.0f - t) * col_sr + t * col_er; + col_g = (1.0f - t) * col_sg + t * col_eg; + col_b = (1.0f - t) * col_sb + t * col_eb; + col_a = (1.0f - t) * col_sa + t * col_ea; + + pixel_r = col_r; + pixel_g = col_g; + pixel_b = col_b; + pixel_a = col_a; + + if (nFlags & GFX3D::RENDER_TEXTURED) + { + if (spr != nullptr) + { + olc::Pixel sample = spr->Sample(tex_u / tex_w, tex_v / tex_w); + pixel_r *= sample.r / 255.0f; + pixel_g *= sample.g / 255.0f; + pixel_b *= sample.b / 255.0f; + pixel_a *= sample.a / 255.0f; + } + } + + if (nFlags & GFX3D::RENDER_DEPTH) + { + if (tex_w > m_DepthBuffer[i*pge->ScreenWidth() + j]) + if (pge->Draw(j, i, olc::Pixel(pixel_r * 1.0f, pixel_g * 1.0f, pixel_b * 1.0f, pixel_a * 1.0f))) + m_DepthBuffer[i*pge->ScreenWidth() + j] = tex_w; + } + else + { + pge->Draw(j, i, olc::Pixel(pixel_r * 1.0f, pixel_g * 1.0f, pixel_b * 1.0f, pixel_a * 1.0f)); + } + + t += tstep; + } + } + } + } + + + + //GFX3D::MipMap::MipMap() : olc::Sprite(){} + //GFX3D::MipMap::MipMap(std::string sImageFile) : olc::Sprite(sImageFile) + //{ + // GenerateMipLevels(); + //} + //GFX3D::MipMap::MipMap(std::string sImageFile, olc::ResourcePack *pack) : olc::Sprite(sImageFile, pack){} + //GFX3D::MipMap::MipMap(int32_t w, int32_t h) : olc::Sprite(w, h) {} + + //int GFX3D::MipMap::GenerateMipLevels() + //{ + // int nLevelsW = 0; + // int nLevelsH = 0; + // int w = width; + // int h = height; + // while (w > 1) { w >>= 1; nLevelsW++; } + // while (h > 1) { h >>= 1; nLevelsH++; } + + // int nLevels = std::min(nLevelsW, nLevelsH); + + // w = width >> 1; + // h = height >> 1; + + // vecMipMaps.emplace_back(w, h); // Level 0 + // memcpy(vecMipMaps[0].GetData(), GetData(), w*h*sizeof(uint32_t)); + + // for (int i = 1; i < nLevels; i++) + // { + // vecMipMaps.emplace_back(w, h); + // pge->SetDrawTarget(&vecMipMaps[i]); + // for (int x = 0; x < w; x++) + // for (int y = 0; y < h; y++) + // pge->Draw(x, y, vecMipMaps[i-1].SampleBL((float)x / (float)w, (float)y / (float)h)); + // w >>= 1; h >>= 1; + // } + + // pge->SetDrawTarget(nullptr); + // return nLevels; + //} + // + //olc::rcode GFX3D::MipMap::LoadFromFile(std::string sImageFile, olc::ResourcePack *pack) + //{ + // olc::rcode r = olc::Sprite::LoadFromFile(sImageFile, pack); + // if (r == olc::FAIL) return r; + // GenerateMipLevels(); + // return r; + //} + + //olc::rcode GFX3D::MipMap::LoadFromPGESprFile(std::string sImageFile, olc::ResourcePack *pack) + //{ + // olc::rcode r = olc::Sprite::LoadFromPGESprFile(sImageFile, pack); + // if (r == olc::FAIL) return r; + // GenerateMipLevels(); + // return r; + //} + // + //olc::Pixel GFX3D::MipMap::Sample(float x, float y, float z) + //{ + // int nLevel = (int)(z * (float)vecMipMaps.size()); + // return vecMipMaps[nLevel].Sample(x, y); + //} + + //olc::Pixel GFX3D::MipMap::SampleBL(float u, float v, float z); + +} + +#endif \ No newline at end of file diff --git a/CarCrimeCity/Part2/olcPixelGameEngine.cpp b/CarCrimeCity/Part2/olcPixelGameEngine.cpp new file mode 100644 index 0000000..b534fc4 --- /dev/null +++ b/CarCrimeCity/Part2/olcPixelGameEngine.cpp @@ -0,0 +1,5 @@ +#define OLC_PGE_APPLICATION +#include "olcPixelGameEngine.h" + +#define OLC_PGEX_GRAPHICS3D +#include "olcPGEX_Graphics3D.h" diff --git a/CarCrimeCity/Part2/olcPixelGameEngine.h b/CarCrimeCity/Part2/olcPixelGameEngine.h new file mode 100644 index 0000000..c691d9d --- /dev/null +++ b/CarCrimeCity/Part2/olcPixelGameEngine.h @@ -0,0 +1,2317 @@ +/* + olcPixelGameEngine.h + + +-------------------------------------------------------------+ + | OneLoneCoder Pixel Game Engine v1.17 | + | "Like the command prompt console one, but not..." - javidx9 | + +-------------------------------------------------------------+ + + What is this? + ~~~~~~~~~~~~~ + The olcConsoleGameEngine has been a surprising and wonderful success for me, + and I'm delighted how people have reacted so positively towards it, so thanks + for that. + + However, there are limitations that I simply cannot avoid. Firstly, I need to + maintain several different versions of it to accommodate users on Windows7, + 8, 10, Linux, Mac, Visual Studio & Code::Blocks. Secondly, this year I've been + pushing the console to the limits of its graphical capabilities and the effect + is becoming underwhelming. The engine itself is not slow at all, but the process + that Windows uses to draw the command prompt to the screen is, and worse still, + it's dynamic based upon the variation of character colours and glyphs. Sadly + I have no control over this, and recent videos that are extremely graphical + (for a command prompt :P ) have been dipping to unacceptable framerates. As + the channel has been popular with aspiring game developers, I'm concerned that + the visual appeal of the command prompt is perhaps limited to us oldies, and I + dont want to alienate younger learners. Finally, I'd like to demonstrate many + more algorithms and image processing that exist in the graphical domain, for + which the console is insufficient. + + For this reason, I have created olcPixelGameEngine! The look and feel to the + programmer is almost identical, so all of my existing code from the videos is + easily portable, and the programmer uses this file in exactly the same way. But + I've decided that rather than just build a command prompt emulator, that I + would at least harness some modern(ish) portable technologies. + + As a result, the olcPixelGameEngine supports 32-bit colour, is written in a + cross-platform style, uses modern(ish) C++ conventions and most importantly, + renders much much faster. I will use this version when my applications are + predominantly graphics based, but use the console version when they are + predominantly text based - Don't worry, loads more command prompt silliness to + come yet, but evolution is important!! + + License (OLC-3) + ~~~~~~~~~~~~~~~ + + Copyright 2018 - 2019 OneLoneCoder.com + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions or derivations of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions or derivative works in binary form must reproduce the above + copyright notice. This list of conditions and the following disclaimer must be + reproduced in the documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors may + be used to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Links + ~~~~~ + YouTube: https://www.youtube.com/javidx9 + https://www.youtube.com/javidx9extra + Discord: https://discord.gg/WhwHUMV + Twitter: https://www.twitter.com/javidx9 + Twitch: https://www.twitch.tv/javidx9 + GitHub: https://www.github.com/onelonecoder + Homepage: https://www.onelonecoder.com + Patreon: https://www.patreon.com/javidx9 + + Relevant Videos + ~~~~~~~~~~~~~~~ + https://youtu.be/kRH6oJLFYxY Introducing olcPixelGameEngine + + Compiling in Linux + ~~~~~~~~~~~~~~~~~~ + You will need a modern C++ compiler, so update yours! + To compile use the command: + + g++ -o YourProgName YourSource.cpp -lX11 -lGL -lpthread -lpng + + On some Linux configurations, the frame rate is locked to the refresh + rate of the monitor. This engine tries to unlock it but may not be + able to, in which case try launching your program like this: + + vblank_mode=0 ./YourProgName + + + Compiling in Code::Blocks on Windows + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Well I wont judge you, but make sure your Code::Blocks installation + is really up to date - you may even consider updating your C++ toolchain + to use MinGW32-W64, so google this. You will also need to enable C++14 + in your build options, and add to your linker the following libraries: + user32 gdi32 opengl32 gdiplus + + Ports + ~~~~~ + olc::PixelGameEngine has been ported and tested with varying degrees of + success to: WinXP, Win7, Win8, Win10, Various Linux, Rapberry Pi, + Chromebook, Playstation Portable (PSP) and Nintendo Switch. If you are + interested in the details of these ports, come and visit the Discord! + + Thanks + ~~~~~~ + I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim, + JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice + Ralakus, Gorbit99, raoul, joshinils, benedani & MagetzUb for advice, ideas and + testing, and I'd like to extend my appreciation to the 40K YouTube followers, + 22 Patreons and 2.6K Discord server members who give me the motivation to keep + going with all this :D + + Special thanks to those who bring gifts! + GnarGnarHead.......Domina + Gorbit99...........Bastion, Ori & The Blind Forest + Marti Morta........Gris + + Special thanks to my Patreons too - I wont name you on here, but I've + certainly enjoyed my tea and flapjacks :D + + Author + ~~~~~~ + David Barr, aka javidx9, ©OneLoneCoder 2018, 2019 +*/ + +////////////////////////////////////////////////////////////////////////////////////////// + +/* Example Usage (main.cpp) + #define OLC_PGE_APPLICATION + #include "olcPixelGameEngine.h" + // Override base class with your custom functionality + class Example : public olc::PixelGameEngine + { + public: + Example() + { + sAppName = "Example"; + } + public: + bool OnUserCreate() override + { + // Called once at the start, so create things here + return true; + } + bool OnUserUpdate(float fElapsedTime) override + { + // called once per frame, draws random coloured pixels + for (int x = 0; x < ScreenWidth(); x++) + for (int y = 0; y < ScreenHeight(); y++) + Draw(x, y, olc::Pixel(rand() % 255, rand() % 255, rand()% 255)); + return true; + } + }; + int main() + { + Example demo; + if (demo.Construct(256, 240, 4, 4)) + demo.Start(); + return 0; + } +*/ + +#ifndef OLC_PGE_DEF +#define OLC_PGE_DEF + +#ifdef _WIN32 + // Link to libraries +#ifndef __MINGW32__ + #pragma comment(lib, "user32.lib") // Visual Studio Only + #pragma comment(lib, "gdi32.lib") // For other Windows Compilers please add + #pragma comment(lib, "opengl32.lib") // these libs to your linker input + #pragma comment(lib, "gdiplus.lib") +#else + // In Code::Blocks, Select C++14 in your build options, and add the + // following libs to your linker: user32 gdi32 opengl32 gdiplus + #if !defined _WIN32_WINNT + #ifdef HAVE_MSMF + #define _WIN32_WINNT 0x0600 // Windows Vista + #else + #define _WIN32_WINNT 0x0500 // Windows 2000 + #endif + #endif +#endif + // Include WinAPI + #include + #include + + // OpenGL Extension + #include + typedef BOOL(WINAPI wglSwapInterval_t) (int interval); + static wglSwapInterval_t *wglSwapInterval; +#else + #include + #include + #include + #include + #include + typedef int(glSwapInterval_t) (Display *dpy, GLXDrawable drawable, int interval); + static glSwapInterval_t *glSwapIntervalEXT; +#endif + + +// Standard includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef min +#undef max + +namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace +{ + struct Pixel + { + union + { + uint32_t n = 0xFF000000; + struct + { + uint8_t r; uint8_t g; uint8_t b; uint8_t a; + }; + }; + + Pixel(); + Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255); + Pixel(uint32_t p); + enum Mode { NORMAL, MASK, ALPHA, CUSTOM }; + }; + + // Some constants for symbolic naming of Pixels + static const Pixel + WHITE(255, 255, 255), + GREY(192, 192, 192), DARK_GREY(128, 128, 128), VERY_DARK_GREY(64, 64, 64), + RED(255, 0, 0), DARK_RED(128, 0, 0), VERY_DARK_RED(64, 0, 0), + YELLOW(255, 255, 0), DARK_YELLOW(128, 128, 0), VERY_DARK_YELLOW(64, 64, 0), + GREEN(0, 255, 0), DARK_GREEN(0, 128, 0), VERY_DARK_GREEN(0, 64, 0), + CYAN(0, 255, 255), DARK_CYAN(0, 128, 128), VERY_DARK_CYAN(0, 64, 64), + BLUE(0, 0, 255), DARK_BLUE(0, 0, 128), VERY_DARK_BLUE(0, 0, 64), + MAGENTA(255, 0, 255), DARK_MAGENTA(128, 0, 128), VERY_DARK_MAGENTA(64, 0, 64), + BLACK(0, 0, 0), + BLANK(0, 0, 0, 0); + + enum rcode + { + FAIL = 0, + OK = 1, + NO_FILE = -1, + }; + + //================================================================================== + + template + struct v2d_generic + { + T x = 0; + T y = 0; + + inline v2d_generic() : x(0), y(0) { } + inline v2d_generic(T _x, T _y) : x(_x), y(_y) { } + inline v2d_generic(const v2d_generic& v) : x(v.x), y(v.y){ } + inline T mag() { return sqrt(x * x + y * y); } + inline v2d_generic norm() { T r = 1 / mag(); return v2d_generic(x*r, y*r); } + inline v2d_generic perp() { return v2d_generic(-y, x); } + inline T dot(const v2d_generic& rhs) { return this->x * rhs.x + this->y * rhs.y; } + inline T cross(const v2d_generic& rhs) { return this->x * rhs.y - this->y * rhs.x; } + inline v2d_generic operator + (const v2d_generic& rhs) const { return v2d_generic(this->x + rhs.x, this->y + rhs.y);} + inline v2d_generic operator - (const v2d_generic& rhs) const { return v2d_generic(this->x - rhs.x, this->y - rhs.y);} + inline v2d_generic operator * (const T& rhs) const { return v2d_generic(this->x * rhs, this->y * rhs); } + inline v2d_generic operator / (const T& rhs) const { return v2d_generic(this->x / rhs, this->y / rhs); } + inline v2d_generic& operator += (const v2d_generic& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; } + inline v2d_generic& operator -= (const v2d_generic& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; } + inline v2d_generic& operator *= (const T& rhs) { this->x *= rhs; this->y *= rhs; return *this; } + inline v2d_generic& operator /= (const T& rhs) { this->x /= rhs; this->y /= rhs; return *this; } + inline T& operator [] (std::size_t i) { return *((T*)this + i); /* <-- D'oh :( */ } + }; + + template inline v2d_generic operator * (const float& lhs, const v2d_generic& rhs) { return v2d_generic(lhs * rhs.x, lhs * rhs.y); } + template inline v2d_generic operator * (const double& lhs, const v2d_generic& rhs){ return v2d_generic(lhs * rhs.x, lhs * rhs.y); } + template inline v2d_generic operator * (const int& lhs, const v2d_generic& rhs) { return v2d_generic(lhs * rhs.x, lhs * rhs.y); } + template inline v2d_generic operator / (const float& lhs, const v2d_generic& rhs) { return v2d_generic(lhs / rhs.x, lhs / rhs.y); } + template inline v2d_generic operator / (const double& lhs, const v2d_generic& rhs){ return v2d_generic(lhs / rhs.x, lhs / rhs.y); } + template inline v2d_generic operator / (const int& lhs, const v2d_generic& rhs) { return v2d_generic(lhs / rhs.x, lhs / rhs.y); } + + typedef v2d_generic vi2d; + typedef v2d_generic vf2d; + typedef v2d_generic vd2d; + + //============================================================= + + struct HWButton + { + bool bPressed = false; // Set once during the frame the event occurs + bool bReleased = false; // Set once during the frame the event occurs + bool bHeld = false; // Set true for all frames between pressed and released events + }; + + //============================================================= + + + class ResourcePack + { + public: + ResourcePack(); + ~ResourcePack(); + struct sEntry : public std::streambuf { + uint32_t nID, nFileOffset, nFileSize; uint8_t* data; void _config() { this->setg((char*)data, (char*)data, (char*)(data + nFileSize)); } + }; + + public: + olc::rcode AddToPack(std::string sFile); + + public: + olc::rcode SavePack(std::string sFile); + olc::rcode LoadPack(std::string sFile); + olc::rcode ClearPack(); + + public: + olc::ResourcePack::sEntry GetStreamBuffer(std::string sFile); + + private: + + std::map mapFiles; + }; + + //============================================================= + + // A bitmap-like structure that stores a 2D array of Pixels + class Sprite + { + public: + Sprite(); + Sprite(std::string sImageFile); + Sprite(std::string sImageFile, olc::ResourcePack *pack); + Sprite(int32_t w, int32_t h); + ~Sprite(); + + public: + olc::rcode LoadFromFile(std::string sImageFile, olc::ResourcePack *pack = nullptr); + olc::rcode LoadFromPGESprFile(std::string sImageFile, olc::ResourcePack *pack = nullptr); + olc::rcode SaveToPGESprFile(std::string sImageFile); + + public: + int32_t width = 0; + int32_t height = 0; + enum Mode { NORMAL, PERIODIC }; + + public: + void SetSampleMode(olc::Sprite::Mode mode = olc::Sprite::Mode::NORMAL); + Pixel GetPixel(int32_t x, int32_t y); + bool SetPixel(int32_t x, int32_t y, Pixel p); + + Pixel Sample(float x, float y); + Pixel SampleBL(float u, float v); + Pixel* GetData(); + + private: + Pixel *pColData = nullptr; + Mode modeSample = Mode::NORMAL; + +#ifdef OLC_DBG_OVERDRAW + public: + static int nOverdrawCount; +#endif + + }; + + //============================================================= + + enum Key + { + NONE, + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, + K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, + UP, DOWN, LEFT, RIGHT, + SPACE, TAB, SHIFT, CTRL, INS, DEL, HOME, END, PGUP, PGDN, + BACK, ESCAPE, RETURN, ENTER, PAUSE, SCROLL, + NP0, NP1, NP2, NP3, NP4, NP5, NP6, NP7, NP8, NP9, + NP_MUL, NP_DIV, NP_ADD, NP_SUB, NP_DECIMAL, + }; + + + //============================================================= + + class PixelGameEngine + { + public: + PixelGameEngine(); + + public: + olc::rcode Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h, bool full_screen = false); + olc::rcode Start(); + + public: // Override Interfaces + // Called once on application startup, use to load your resources + virtual bool OnUserCreate(); + // Called every frame, and provides you with a time per frame value + virtual bool OnUserUpdate(float fElapsedTime); + // Called once on application termination, so you can be a clean coder + virtual bool OnUserDestroy(); + + public: // Hardware Interfaces + // Returns true if window is currently in focus + bool IsFocused(); + // Get the state of a specific keyboard button + HWButton GetKey(Key k); + // Get the state of a specific mouse button + HWButton GetMouse(uint32_t b); + // Get Mouse X coordinate in "pixel" space + int32_t GetMouseX(); + // Get Mouse Y coordinate in "pixel" space + int32_t GetMouseY(); + // Get Mouse Wheel Delta + int32_t GetMouseWheel(); + + public: // Utility + // Returns the width of the screen in "pixels" + int32_t ScreenWidth(); + // Returns the height of the screen in "pixels" + int32_t ScreenHeight(); + // Returns the width of the currently selected drawing target in "pixels" + int32_t GetDrawTargetWidth(); + // Returns the height of the currently selected drawing target in "pixels" + int32_t GetDrawTargetHeight(); + // Returns the currently active draw target + Sprite* GetDrawTarget(); + + public: // Draw Routines + // Specify which Sprite should be the target of drawing functions, use nullptr + // to specify the primary screen + void SetDrawTarget(Sprite *target); + // Change the pixel mode for different optimisations + // olc::Pixel::NORMAL = No transparency + // olc::Pixel::MASK = Transparent if alpha is < 255 + // olc::Pixel::ALPHA = Full transparency + void SetPixelMode(Pixel::Mode m); + Pixel::Mode GetPixelMode(); + // Use a custom blend function + void SetPixelMode(std::function pixelMode); + // Change the blend factor form between 0.0f to 1.0f; + void SetPixelBlend(float fBlend); + // Offset texels by sub-pixel amount (advanced, do not use) + void SetSubPixelOffset(float ox, float oy); + + // Draws a single Pixel + virtual bool Draw(int32_t x, int32_t y, Pixel p = olc::WHITE); + // Draws a line from (x1,y1) to (x2,y2) + void DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF); + // Draws a circle located at (x,y) with radius + void DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF); + // Fills a circle located at (x,y) with radius + void FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE); + // Draws a rectangle at (x,y) to (x+w,y+h) + void DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE); + // Fills a rectangle at (x,y) to (x+w,y+h) + void FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE); + // Draws a triangle between points (x1,y1), (x2,y2) and (x3,y3) + void DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); + // Flat fills a triangle between points (x1,y1), (x2,y2) and (x3,y3) + void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); + // Draws an entire sprite at location (x,y) + void DrawSprite(int32_t x, int32_t y, Sprite *sprite, uint32_t scale = 1); + // Draws an area of a sprite at location (x,y), where the + // selected area is (ox,oy) to (ox+w,oy+h) + void DrawPartialSprite(int32_t x, int32_t y, Sprite *sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale = 1); + // Draws a single line of text + void DrawString(int32_t x, int32_t y, std::string sText, Pixel col = olc::WHITE, uint32_t scale = 1); + // Clears entire draw target to Pixel + void Clear(Pixel p); + + public: // Branding + std::string sAppName; + + private: // Inner mysterious workings + Sprite *pDefaultDrawTarget = nullptr; + Sprite *pDrawTarget = nullptr; + Pixel::Mode nPixelMode = Pixel::NORMAL; + float fBlendFactor = 1.0f; + uint32_t nScreenWidth = 256; + uint32_t nScreenHeight = 240; + uint32_t nPixelWidth = 4; + uint32_t nPixelHeight = 4; + int32_t nMousePosX = 0; + int32_t nMousePosY = 0; + int32_t nMouseWheelDelta = 0; + int32_t nMousePosXcache = 0; + int32_t nMousePosYcache = 0; + int32_t nMouseWheelDeltaCache = 0; + int32_t nWindowWidth = 0; + int32_t nWindowHeight = 0; + int32_t nViewX = 0; + int32_t nViewY = 0; + int32_t nViewW = 0; + int32_t nViewH = 0; + bool bFullScreen = false; + float fPixelX = 1.0f; + float fPixelY = 1.0f; + float fSubPixelOffsetX = 0.0f; + float fSubPixelOffsetY = 0.0f; + bool bHasInputFocus = false; + bool bHasMouseFocus = false; + float fFrameTimer = 1.0f; + int nFrameCount = 0; + Sprite *fontSprite = nullptr; + std::function funcPixelMode; + + static std::map mapKeys; + bool pKeyNewState[256]{ 0 }; + bool pKeyOldState[256]{ 0 }; + HWButton pKeyboardState[256]; + + bool pMouseNewState[5]{ 0 }; + bool pMouseOldState[5]{ 0 }; + HWButton pMouseState[5]; + +#ifdef _WIN32 + HDC glDeviceContext = nullptr; + HGLRC glRenderContext = nullptr; +#else + GLXContext glDeviceContext = nullptr; + GLXContext glRenderContext = nullptr; +#endif + GLuint glBuffer; + + void EngineThread(); + + // If anything sets this flag to false, the engine + // "should" shut down gracefully + static std::atomic bAtomActive; + + // Common initialisation functions + void olc_UpdateMouse(int32_t x, int32_t y); + void olc_UpdateMouseWheel(int32_t delta); + void olc_UpdateWindowSize(int32_t x, int32_t y); + void olc_UpdateViewport(); + bool olc_OpenGLCreate(); + void olc_ConstructFontSheet(); + + +#ifdef _WIN32 + // Windows specific window handling + HWND olc_hWnd = nullptr; + HWND olc_WindowCreate(); + std::wstring wsAppName; + static LRESULT CALLBACK olc_WindowEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +#else + // Non-Windows specific window handling + Display* olc_Display = nullptr; + Window olc_WindowRoot; + Window olc_Window; + XVisualInfo* olc_VisualInfo; + Colormap olc_ColourMap; + XSetWindowAttributes olc_SetWindowAttribs; + Display* olc_WindowCreate(); +#endif + + }; + + + class PGEX + { + friend class olc::PixelGameEngine; + protected: + static PixelGameEngine* pge; + }; + + //============================================================= +} + +#endif // OLC_PGE_DEF + + + + +/* + Object Oriented Mode + ~~~~~~~~~~~~~~~~~~~~ + + If the olcPixelGameEngine.h is called from several sources it can cause + multiple definitions of objects. To prevent this, ONLY ONE of the pathways + to including this file must have OLC_PGE_APPLICATION defined before it. This prevents + the definitions being duplicated. + + If all else fails, create a file called "olcPixelGameEngine.cpp" with the following + two lines. Then you can just #include "olcPixelGameEngine.h" as normal without worrying + about defining things. Dont forget to include that cpp file as part of your build! + + #define OLC_PGE_APPLICATION + #include "olcPixelGameEngine.h" + +*/ + +#ifdef OLC_PGE_APPLICATION +#undef OLC_PGE_APPLICATION + +namespace olc +{ + Pixel::Pixel() + { + r = 0; g = 0; b = 0; a = 255; + } + + Pixel::Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) + { + r = red; g = green; b = blue; a = alpha; + } + + Pixel::Pixel(uint32_t p) + { + n = p; + } + + //========================================================== + + std::wstring ConvertS2W(std::string s) + { +#ifdef _WIN32 + int count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); + wchar_t* buffer = new wchar_t[count]; + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, buffer, count); + std::wstring w(buffer); + delete[] buffer; + return w; +#else + return L"SVN FTW!"; +#endif + } + + Sprite::Sprite() + { + pColData = nullptr; + width = 0; + height = 0; + } + + Sprite::Sprite(std::string sImageFile) + { + LoadFromFile(sImageFile); + } + + Sprite::Sprite(std::string sImageFile, olc::ResourcePack *pack) + { + LoadFromPGESprFile(sImageFile, pack); + } + + Sprite::Sprite(int32_t w, int32_t h) + { + if(pColData) delete[] pColData; + width = w; height = h; + pColData = new Pixel[width * height]; + for (int32_t i = 0; i < width*height; i++) + pColData[i] = Pixel(); + } + + Sprite::~Sprite() + { + if (pColData) delete pColData; + } + + olc::rcode Sprite::LoadFromPGESprFile(std::string sImageFile, olc::ResourcePack *pack) + { + if (pColData) delete[] pColData; + + auto ReadData = [&](std::istream &is) + { + is.read((char*)&width, sizeof(int32_t)); + is.read((char*)&height, sizeof(int32_t)); + pColData = new Pixel[width * height]; + is.read((char*)pColData, width * height * sizeof(uint32_t)); + }; + + // These are essentially Memory Surfaces represented by olc::Sprite + // which load very fast, but are completely uncompressed + if (pack == nullptr) + { + std::ifstream ifs; + ifs.open(sImageFile, std::ifstream::binary); + if (ifs.is_open()) + { + ReadData(ifs); + return olc::OK; + } + else + return olc::FAIL; + } + else + { + auto streamBuffer = pack->GetStreamBuffer(sImageFile); + std::istream is(&streamBuffer); + ReadData(is); + } + + + return olc::FAIL; + } + + olc::rcode Sprite::SaveToPGESprFile(std::string sImageFile) + { + if (pColData == nullptr) return olc::FAIL; + + std::ofstream ofs; + ofs.open(sImageFile, std::ifstream::binary); + if (ofs.is_open()) + { + ofs.write((char*)&width, sizeof(int32_t)); + ofs.write((char*)&height, sizeof(int32_t)); + ofs.write((char*)pColData, width*height*sizeof(uint32_t)); + ofs.close(); + return olc::OK; + } + + return olc::FAIL; + } + + olc::rcode Sprite::LoadFromFile(std::string sImageFile, olc::ResourcePack *pack) + { +#ifdef _WIN32 + // Use GDI+ + std::wstring wsImageFile; +#ifdef __MINGW32__ + wchar_t *buffer = new wchar_t[sImageFile.length() + 1]; + mbstowcs(buffer, sImageFile.c_str(), sImageFile.length()); + buffer[sImageFile.length()] = L'\0'; + wsImageFile = buffer; + delete [] buffer; +#else + wsImageFile = ConvertS2W(sImageFile); +#endif + Gdiplus::Bitmap *bmp = Gdiplus::Bitmap::FromFile(wsImageFile.c_str()); + if (bmp == nullptr) + return olc::NO_FILE; + + width = bmp->GetWidth(); + height = bmp->GetHeight(); + pColData = new Pixel[width * height]; + + for(int x=0; xGetPixel(x, y, &c); + SetPixel(x, y, Pixel(c.GetRed(), c.GetGreen(), c.GetBlue(), c.GetAlpha())); + } + delete bmp; + return olc::OK; +#else + //////////////////////////////////////////////////////////////////////////// + // Use libpng, Thanks to Guillaume Cottenceau + // https://gist.github.com/niw/5963798 + png_structp png; + png_infop info; + + FILE *f = fopen(sImageFile.c_str(), "rb"); + if (!f) return olc::NO_FILE; + + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png) goto fail_load; + + info = png_create_info_struct(png); + if (!info) goto fail_load; + + if (setjmp(png_jmpbuf(png))) goto fail_load; + + png_init_io(png, f); + png_read_info(png, info); + + png_byte color_type; + png_byte bit_depth; + png_bytep *row_pointers; + width = png_get_image_width(png, info); + height = png_get_image_height(png, info); + color_type = png_get_color_type(png, info); + bit_depth = png_get_bit_depth(png, info); + +#ifdef _DEBUG + std::cout << "Loading PNG: " << sImageFile << "\n"; + std::cout << "W:" << width << " H:" << height << " D:" << (int)bit_depth << "\n"; +#endif + + if (bit_depth == 16) png_set_strip_16(png); + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); + if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_PALETTE) + png_set_filler(png, 0xFF, PNG_FILLER_AFTER); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png); + + png_read_update_info(png, info); + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); + for (int y = 0; y < height; y++) { + row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info)); + } + png_read_image(png, row_pointers); + //////////////////////////////////////////////////////////////////////////// + + // Create sprite array + pColData = new Pixel[width * height]; + + // Iterate through image rows, converting into sprite format + for (int y = 0; y < height; y++) + { + png_bytep row = row_pointers[y]; + for (int x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + SetPixel(x, y, Pixel(px[0], px[1], px[2], px[3])); + } + } + + fclose(f); + return olc::OK; + + fail_load: + width = 0; + height = 0; + fclose(f); + pColData = nullptr; + return olc::FAIL; +#endif + } + + void Sprite::SetSampleMode(olc::Sprite::Mode mode) + { + modeSample = mode; + } + + + Pixel Sprite::GetPixel(int32_t x, int32_t y) + { + if (modeSample == olc::Sprite::Mode::NORMAL) + { + if (x >= 0 && x < width && y >= 0 && y < height) + return pColData[y*width + x]; + else + return Pixel(0, 0, 0, 0); + } + else + { + return pColData[abs(y%height)*width + abs(x%width)]; + } + } + + bool Sprite::SetPixel(int32_t x, int32_t y, Pixel p) + { + +#ifdef OLC_DBG_OVERDRAW + nOverdrawCount++; +#endif + + if (x >= 0 && x < width && y >= 0 && y < height) + { + pColData[y*width + x] = p; + return true; + } + else + return false; + } + + Pixel Sprite::Sample(float x, float y) + { + int32_t sx = std::min((int32_t)((x * (float)width)), width - 1); + int32_t sy = std::min((int32_t)((y * (float)height)), height - 1); + return GetPixel(sx, sy); + } + + Pixel Sprite::SampleBL(float u, float v) + { + u = u * width - 0.5f; + v = v * height - 0.5f; + int x = (int)floor(u); // cast to int rounds toward zero, not downward + int y = (int)floor(v); // Thanks @joshinils + float u_ratio = u - x; + float v_ratio = v - y; + float u_opposite = 1 - u_ratio; + float v_opposite = 1 - v_ratio; + + olc::Pixel p1 = GetPixel(std::max(x, 0), std::max(y, 0)); + olc::Pixel p2 = GetPixel(std::min(x + 1, (int)width - 1), std::max(y, 0)); + olc::Pixel p3 = GetPixel(std::max(x, 0), std::min(y + 1, (int)height - 1)); + olc::Pixel p4 = GetPixel(std::min(x + 1, (int)width - 1), std::min(y + 1, (int)height - 1)); + + return olc::Pixel( + (uint8_t)((p1.r * u_opposite + p2.r * u_ratio) * v_opposite + (p3.r * u_opposite + p4.r * u_ratio) * v_ratio), + (uint8_t)((p1.g * u_opposite + p2.g * u_ratio) * v_opposite + (p3.g * u_opposite + p4.g * u_ratio) * v_ratio), + (uint8_t)((p1.b * u_opposite + p2.b * u_ratio) * v_opposite + (p3.b * u_opposite + p4.b * u_ratio) * v_ratio)); + } + + Pixel* Sprite::GetData() { return pColData; } + + //========================================================== + + ResourcePack::ResourcePack() + { + + } + + ResourcePack::~ResourcePack() + { + ClearPack(); + } + + olc::rcode ResourcePack::AddToPack(std::string sFile) + { + std::ifstream ifs(sFile, std::ifstream::binary); + if (!ifs.is_open()) return olc::FAIL; + + // Get File Size + std::streampos p = 0; + p = ifs.tellg(); + ifs.seekg(0, std::ios::end); + p = ifs.tellg() - p; + ifs.seekg(0, std::ios::beg); + + // Create entry + sEntry e; + e.data = nullptr; + e.nFileSize = (uint32_t)p; + + // Read file into memory + e.data = new uint8_t[(uint32_t)e.nFileSize]; + ifs.read((char*)e.data, e.nFileSize); + ifs.close(); + + // Add To Map + mapFiles[sFile] = e; + return olc::OK; + } + + olc::rcode ResourcePack::SavePack(std::string sFile) + { + std::ofstream ofs(sFile, std::ofstream::binary); + if (!ofs.is_open()) return olc::FAIL; + + // 1) Write Map + size_t nMapSize = mapFiles.size(); + ofs.write((char*)&nMapSize, sizeof(size_t)); + for (auto &e : mapFiles) + { + size_t nPathSize = e.first.size(); + ofs.write((char*)&nPathSize, sizeof(size_t)); + ofs.write(e.first.c_str(), nPathSize); + ofs.write((char*)&e.second.nID, sizeof(uint32_t)); + ofs.write((char*)&e.second.nFileSize, sizeof(uint32_t)); + ofs.write((char*)&e.second.nFileOffset, sizeof(uint32_t)); + } + + // 2) Write Data + std::streampos offset = ofs.tellp(); + for (auto &e : mapFiles) + { + e.second.nFileOffset = (uint32_t)offset; + ofs.write((char*)e.second.data, e.second.nFileSize); + offset += e.second.nFileSize; + } + + // 3) Rewrite Map (it has been updated with offsets now) + ofs.seekp(std::ios::beg); + ofs.write((char*)&nMapSize, sizeof(size_t)); + for (auto &e : mapFiles) + { + size_t nPathSize = e.first.size(); + ofs.write((char*)&nPathSize, sizeof(size_t)); + ofs.write(e.first.c_str(), nPathSize); + ofs.write((char*)&e.second.nID, sizeof(uint32_t)); + ofs.write((char*)&e.second.nFileSize, sizeof(uint32_t)); + ofs.write((char*)&e.second.nFileOffset, sizeof(uint32_t)); + } + ofs.close(); + + return olc::OK; + } + + olc::rcode ResourcePack::LoadPack(std::string sFile) + { + std::ifstream ifs(sFile, std::ifstream::binary); + if (!ifs.is_open()) return olc::FAIL; + + // 1) Read Map + size_t nMapEntries; + ifs.read((char*)&nMapEntries, sizeof(size_t)); + for (size_t i = 0; i < nMapEntries; i++) + { + size_t nFilePathSize = 0; + ifs.read((char*)&nFilePathSize, sizeof(size_t)); + + std::string sFileName(nFilePathSize, ' '); + for (size_t j = 0; j < nFilePathSize; j++) + sFileName[j] = ifs.get(); + + sEntry e; + e.data = nullptr; + ifs.read((char*)&e.nID, sizeof(uint32_t)); + ifs.read((char*)&e.nFileSize, sizeof(uint32_t)); + ifs.read((char*)&e.nFileOffset, sizeof(uint32_t)); + mapFiles[sFileName] = e; + } + + // 2) Read Data + for (auto &e : mapFiles) + { + e.second.data = new uint8_t[(uint32_t)e.second.nFileSize]; + ifs.seekg(e.second.nFileOffset); + ifs.read((char*)e.second.data, e.second.nFileSize); + e.second._config(); + } + + ifs.close(); + return olc::OK; + } + + olc::ResourcePack::sEntry ResourcePack::GetStreamBuffer(std::string sFile) + { + return mapFiles[sFile]; + } + + olc::rcode ResourcePack::ClearPack() + { + for (auto &e : mapFiles) + { + if (e.second.data != nullptr) + delete[] e.second.data; + } + + mapFiles.clear(); + return olc::OK; + } + + //========================================================== + + PixelGameEngine::PixelGameEngine() + { + sAppName = "Undefined"; + olc::PGEX::pge = this; + } + + olc::rcode PixelGameEngine::Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h, bool full_screen) + { + nScreenWidth = screen_w; + nScreenHeight = screen_h; + nPixelWidth = pixel_w; + nPixelHeight = pixel_h; + bFullScreen = full_screen; + + fPixelX = 2.0f / (float)(nScreenWidth); + fPixelY = 2.0f / (float)(nScreenHeight); + + if (nPixelWidth == 0 || nPixelHeight == 0 || nScreenWidth == 0 || nScreenHeight == 0) + return olc::FAIL; + +#ifdef _WIN32 +#ifdef UNICODE +#ifndef __MINGW32__ + wsAppName = ConvertS2W(sAppName); +#endif +#endif +#endif + // Load the default font sheet + olc_ConstructFontSheet(); + + // Create a sprite that represents the primary drawing target + pDefaultDrawTarget = new Sprite(nScreenWidth, nScreenHeight); + SetDrawTarget(nullptr); + return olc::OK; + } + + olc::rcode PixelGameEngine::Start() + { + // Construct the window + if (!olc_WindowCreate()) + return olc::FAIL; + + // Load libraries required for PNG file interaction +//#ifdef _WIN32 +// // Windows use GDI+ +// Gdiplus::GdiplusStartupInput startupInput; +// ULONG_PTR token; +// Gdiplus::GdiplusStartup(&token, &startupInput, NULL); +//#else +// // Linux use libpng +// +//#endif + // Start the thread + bAtomActive = true; + std::thread t = std::thread(&PixelGameEngine::EngineThread, this); + +#ifdef _WIN32 + // Handle Windows Message Loop + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +#endif + + // Wait for thread to be exited + t.join(); + return olc::OK; + } + + void PixelGameEngine::SetDrawTarget(Sprite *target) + { + if (target) + pDrawTarget = target; + else + pDrawTarget = pDefaultDrawTarget; + } + + Sprite* PixelGameEngine::GetDrawTarget() + { + return pDrawTarget; + } + + int32_t PixelGameEngine::GetDrawTargetWidth() + { + if (pDrawTarget) + return pDrawTarget->width; + else + return 0; + } + + int32_t PixelGameEngine::GetDrawTargetHeight() + { + if (pDrawTarget) + return pDrawTarget->height; + else + return 0; + } + + bool PixelGameEngine::IsFocused() + { + return bHasInputFocus; + } + + HWButton PixelGameEngine::GetKey(Key k) + { + return pKeyboardState[k]; + } + + HWButton PixelGameEngine::GetMouse(uint32_t b) + { + return pMouseState[b]; + } + + int32_t PixelGameEngine::GetMouseX() + { + return nMousePosX; + } + + int32_t PixelGameEngine::GetMouseY() + { + return nMousePosY; + } + + int32_t PixelGameEngine::GetMouseWheel() + { + return nMouseWheelDelta; + } + + int32_t PixelGameEngine::ScreenWidth() + { + return nScreenWidth; + } + + int32_t PixelGameEngine::ScreenHeight() + { + return nScreenHeight; + } + + bool PixelGameEngine::Draw(int32_t x, int32_t y, Pixel p) + { + if (!pDrawTarget) return false; + + + if (nPixelMode == Pixel::NORMAL) + { + return pDrawTarget->SetPixel(x, y, p); + } + + if (nPixelMode == Pixel::MASK) + { + if(p.a == 255) + return pDrawTarget->SetPixel(x, y, p); + } + + if (nPixelMode == Pixel::ALPHA) + { + Pixel d = pDrawTarget->GetPixel(x, y); + float a = (float)(p.a / 255.0f) * fBlendFactor; + float c = 1.0f - a; + float r = a * (float)p.r + c * (float)d.r; + float g = a * (float)p.g + c * (float)d.g; + float b = a * (float)p.b + c * (float)d.b; + return pDrawTarget->SetPixel(x, y, Pixel((uint8_t)r, (uint8_t)g, (uint8_t)b)); + } + + if (nPixelMode == Pixel::CUSTOM) + { + return pDrawTarget->SetPixel(x, y, funcPixelMode(x, y, p, pDrawTarget->GetPixel(x, y))); + } + + return false; + } + + void PixelGameEngine::SetSubPixelOffset(float ox, float oy) + { + fSubPixelOffsetX = ox * fPixelX; + fSubPixelOffsetY = oy * fPixelY; + } + + void PixelGameEngine::DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p, uint32_t pattern) + { + int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i; + dx = x2 - x1; dy = y2 - y1; + + auto rol = [&](void) + { + pattern = (pattern << 1) | (pattern >> 31); + return pattern & 1; + }; + + // straight lines idea by gurkanctn + if (dx == 0) // Line is vertical + { + if (y2 < y1) std::swap(y1, y2); + for (y = y1; y <= y2; y++) + if (rol()) Draw(x1, y, p); + return; + } + + if (dy == 0) // Line is horizontal + { + if (x2 < x1) std::swap(x1, x2); + for (x = x1; x <= x2; x++) + if (rol()) Draw(x, y1, p); + return; + } + + // Line is Funk-aye + dx1 = abs(dx); dy1 = abs(dy); + px = 2 * dy1 - dx1; py = 2 * dx1 - dy1; + if (dy1 <= dx1) + { + if (dx >= 0) + { + x = x1; y = y1; xe = x2; + } + else + { + x = x2; y = y2; xe = x1; + } + + if (rol()) Draw(x, y, p); + + for (i = 0; x0 && dy>0)) y = y + 1; else y = y - 1; + px = px + 2 * (dy1 - dx1); + } + if (rol()) Draw(x, y, p); + } + } + else + { + if (dy >= 0) + { + x = x1; y = y1; ye = y2; + } + else + { + x = x2; y = y2; ye = y1; + } + + if (rol()) Draw(x, y, p); + + for (i = 0; y0 && dy>0)) x = x + 1; else x = x - 1; + py = py + 2 * (dx1 - dy1); + } + if (rol()) Draw(x, y, p); + } + } + } + + void PixelGameEngine::DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p, uint8_t mask) + { + int x0 = 0; + int y0 = radius; + int d = 3 - 2 * radius; + if (!radius) return; + + while (y0 >= x0) // only formulate 1/8 of circle + { + if (mask & 0x01) Draw(x + x0, y - y0, p); + if (mask & 0x02) Draw(x + y0, y - x0, p); + if (mask & 0x04) Draw(x + y0, y + x0, p); + if (mask & 0x08) Draw(x + x0, y + y0, p); + if (mask & 0x10) Draw(x - x0, y + y0, p); + if (mask & 0x20) Draw(x - y0, y + x0, p); + if (mask & 0x40) Draw(x - y0, y - x0, p); + if (mask & 0x80) Draw(x - x0, y - y0, p); + if (d < 0) d += 4 * x0++ + 6; + else d += 4 * (x0++ - y0--) + 10; + } + } + + void PixelGameEngine::FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p) + { + // Taken from wikipedia + int x0 = 0; + int y0 = radius; + int d = 3 - 2 * radius; + if (!radius) return; + + auto drawline = [&](int sx, int ex, int ny) + { + for (int i = sx; i <= ex; i++) + Draw(i, ny, p); + }; + + while (y0 >= x0) + { + // Modified to draw scan-lines instead of edges + drawline(x - x0, x + x0, y - y0); + drawline(x - y0, x + y0, y - x0); + drawline(x - x0, x + x0, y + y0); + drawline(x - y0, x + y0, y + x0); + if (d < 0) d += 4 * x0++ + 6; + else d += 4 * (x0++ - y0--) + 10; + } + } + + void PixelGameEngine::DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) + { + DrawLine(x, y, x+w, y, p); + DrawLine(x+w, y, x+w, y+h, p); + DrawLine(x+w, y+h, x, y+h, p); + DrawLine(x, y+h, x, y, p); + } + + void PixelGameEngine::Clear(Pixel p) + { + int pixels = GetDrawTargetWidth() * GetDrawTargetHeight(); + Pixel* m = GetDrawTarget()->GetData(); + for (int i = 0; i < pixels; i++) + m[i] = p; +#ifdef OLC_DBG_OVERDRAW + olc::Sprite::nOverdrawCount += pixels; +#endif + } + + void PixelGameEngine::FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) + { + int32_t x2 = x + w; + int32_t y2 = y + h; + + if (x < 0) x = 0; + if (x >= (int32_t)nScreenWidth) x = (int32_t)nScreenWidth; + if (y < 0) y = 0; + if (y >= (int32_t)nScreenHeight) y = (int32_t)nScreenHeight; + + if (x2 < 0) x2 = 0; + if (x2 >= (int32_t)nScreenWidth) x2 = (int32_t)nScreenWidth; + if (y2 < 0) y2 = 0; + if (y2 >= (int32_t)nScreenHeight) y2 = (int32_t)nScreenHeight; + + for (int i = x; i < x2; i++) + for (int j = y; j < y2; j++) + Draw(i, j, p); + } + + void PixelGameEngine::DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) + { + DrawLine(x1, y1, x2, y2, p); + DrawLine(x2, y2, x3, y3, p); + DrawLine(x3, y3, x1, y1, p); + } + + // https://www.avrfreaks.net/sites/default/files/triangles.c + void PixelGameEngine::FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) + { + auto SWAP = [](int &x, int &y) { int t = x; x = y; y = t; }; + auto drawline = [&](int sx, int ex, int ny) { for (int i = sx; i <= ex; i++) Draw(i, ny, p); }; + + int t1x, t2x, y, minx, maxx, t1xp, t2xp; + bool changed1 = false; + bool changed2 = false; + int signx1, signx2, dx1, dy1, dx2, dy2; + int e1, e2; + // Sort vertices + if (y1>y2) { SWAP(y1, y2); SWAP(x1, x2); } + if (y1>y3) { SWAP(y1, y3); SWAP(x1, x3); } + if (y2>y3) { SWAP(y2, y3); SWAP(x2, x3); } + + t1x = t2x = x1; y = y1; // Starting points + dx1 = (int)(x2 - x1); if (dx1<0) { dx1 = -dx1; signx1 = -1; } + else signx1 = 1; + dy1 = (int)(y2 - y1); + + dx2 = (int)(x3 - x1); if (dx2<0) { dx2 = -dx2; signx2 = -1; } + else signx2 = 1; + dy2 = (int)(y3 - y1); + + if (dy1 > dx1) { // swap values + SWAP(dx1, dy1); + changed1 = true; + } + if (dy2 > dx2) { // swap values + SWAP(dy2, dx2); + changed2 = true; + } + + e2 = (int)(dx2 >> 1); + // Flat top, just process the second half + if (y1 == y2) goto next; + e1 = (int)(dx1 >> 1); + + for (int i = 0; i < dx1;) { + t1xp = 0; t2xp = 0; + if (t1x= dx1) { + e1 -= dx1; + if (changed1) t1xp = signx1;//t1x += signx1; + else goto next1; + } + if (changed1) break; + else t1x += signx1; + } + // Move line + next1: + // process second line until y value is about to change + while (1) { + e2 += dy2; + while (e2 >= dx2) { + e2 -= dx2; + if (changed2) t2xp = signx2;//t2x += signx2; + else goto next2; + } + if (changed2) break; + else t2x += signx2; + } + next2: + if (minx>t1x) minx = t1x; if (minx>t2x) minx = t2x; + if (maxx dx1) { // swap values + SWAP(dy1, dx1); + changed1 = true; + } + else changed1 = false; + + e1 = (int)(dx1 >> 1); + + for (int i = 0; i <= dx1; i++) { + t1xp = 0; t2xp = 0; + if (t1x= dx1) { + e1 -= dx1; + if (changed1) { t1xp = signx1; break; }//t1x += signx1; + else goto next3; + } + if (changed1) break; + else t1x += signx1; + if (i= dx2) { + e2 -= dx2; + if (changed2) t2xp = signx2; + else goto next4; + } + if (changed2) break; + else t2x += signx2; + } + next4: + + if (minx>t1x) minx = t1x; if (minx>t2x) minx = t2x; + if (maxxy3) return; + } + } + + void PixelGameEngine::DrawSprite(int32_t x, int32_t y, Sprite *sprite, uint32_t scale) + { + if (sprite == nullptr) + return; + + if (scale > 1) + { + for (int32_t i = 0; i < sprite->width; i++) + for (int32_t j = 0; j < sprite->height; j++) + for (uint32_t is = 0; is < scale; is++) + for (uint32_t js = 0; js < scale; js++) + Draw(x + (i*scale) + is, y + (j*scale) + js, sprite->GetPixel(i, j)); + } + else + { + for (int32_t i = 0; i < sprite->width; i++) + for (int32_t j = 0; j < sprite->height; j++) + Draw(x + i, y + j, sprite->GetPixel(i, j)); + } + } + + void PixelGameEngine::DrawPartialSprite(int32_t x, int32_t y, Sprite *sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale) + { + if (sprite == nullptr) + return; + + if (scale > 1) + { + for (int32_t i = 0; i < w; i++) + for (int32_t j = 0; j < h; j++) + for (uint32_t is = 0; is < scale; is++) + for (uint32_t js = 0; js < scale; js++) + Draw(x + (i*scale) + is, y + (j*scale) + js, sprite->GetPixel(i + ox, j + oy)); + } + else + { + for (int32_t i = 0; i < w; i++) + for (int32_t j = 0; j < h; j++) + Draw(x + i, y + j, sprite->GetPixel(i + ox, j + oy)); + } + } + + void PixelGameEngine::DrawString(int32_t x, int32_t y, std::string sText, Pixel col, uint32_t scale) + { + int32_t sx = 0; + int32_t sy = 0; + Pixel::Mode m = nPixelMode; + if(col.ALPHA != 255) SetPixelMode(Pixel::ALPHA); + else SetPixelMode(Pixel::MASK); + for (auto c : sText) + { + if (c == '\n') + { + sx = 0; sy += 8 * scale; + } + else + { + int32_t ox = (c - 32) % 16; + int32_t oy = (c - 32) / 16; + + if (scale > 1) + { + for (uint32_t i = 0; i < 8; i++) + for (uint32_t j = 0; j < 8; j++) + if (fontSprite->GetPixel(i + ox * 8, j + oy * 8).r > 0) + for (uint32_t is = 0; is < scale; is++) + for (uint32_t js = 0; js < scale; js++) + Draw(x + sx + (i*scale) + is, y + sy + (j*scale) + js, col); + } + else + { + for (uint32_t i = 0; i < 8; i++) + for (uint32_t j = 0; j < 8; j++) + if (fontSprite->GetPixel(i + ox * 8, j + oy * 8).r > 0) + Draw(x + sx + i, y + sy + j, col); + } + sx += 8 * scale; + } + } + SetPixelMode(m); + } + + void PixelGameEngine::SetPixelMode(Pixel::Mode m) + { + nPixelMode = m; + } + + Pixel::Mode PixelGameEngine::GetPixelMode() + { + return nPixelMode; + } + + void PixelGameEngine::SetPixelMode(std::function pixelMode) + { + funcPixelMode = pixelMode; + nPixelMode = Pixel::Mode::CUSTOM; + } + + void PixelGameEngine::SetPixelBlend(float fBlend) + { + fBlendFactor = fBlend; + if (fBlendFactor < 0.0f) fBlendFactor = 0.0f; + if (fBlendFactor > 1.0f) fBlendFactor = 1.0f; + } + + // User must override these functions as required. I have not made + // them abstract because I do need a default behaviour to occur if + // they are not overwritten + bool PixelGameEngine::OnUserCreate() + { return false; } + bool PixelGameEngine::OnUserUpdate(float fElapsedTime) + { return false; } + bool PixelGameEngine::OnUserDestroy() + { return true; } + ////////////////////////////////////////////////////////////////// + + void PixelGameEngine::olc_UpdateViewport() + { + int32_t ww = nScreenWidth * nPixelWidth; + int32_t wh = nScreenHeight * nPixelHeight; + float wasp = (float)ww / (float)wh; + + nViewW = (int32_t)nWindowWidth; + nViewH = (int32_t)((float)nViewW / wasp); + + if (nViewH > nWindowHeight) + { + nViewH = nWindowHeight; + nViewW = (int32_t)((float)nViewH * wasp); + } + + nViewX = (nWindowWidth - nViewW) / 2; + nViewY = (nWindowHeight - nViewH) / 2; + } + + void PixelGameEngine::olc_UpdateWindowSize(int32_t x, int32_t y) + { + nWindowWidth = x; + nWindowHeight = y; + olc_UpdateViewport(); + + } + + void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta) + { + nMouseWheelDeltaCache += delta; + } + + void PixelGameEngine::olc_UpdateMouse(int32_t x, int32_t y) + { + // Mouse coords come in screen space + // But leave in pixel space + + //if (bFullScreen) + { + // Full Screen mode may have a weird viewport we must clamp to + x -= nViewX; + y -= nViewY; + } + + nMousePosXcache = (int32_t)(((float)x / (float)(nWindowWidth - (nViewX * 2)) * (float)nScreenWidth)); + nMousePosYcache = (int32_t)(((float)y / (float)(nWindowHeight - (nViewY * 2)) * (float)nScreenHeight)); + + if (nMousePosXcache >= (int32_t)nScreenWidth) + nMousePosXcache = nScreenWidth - 1; + if (nMousePosYcache >= (int32_t)nScreenHeight) + nMousePosYcache = nScreenHeight - 1; + + if (nMousePosXcache < 0) + nMousePosXcache = 0; + if (nMousePosYcache < 0) + nMousePosYcache = 0; + } + + void PixelGameEngine::EngineThread() + { + // Start OpenGL, the context is owned by the game thread + olc_OpenGLCreate(); + + // Create Screen Texture - disable filtering + glEnable(GL_TEXTURE_2D); + glGenTextures(1, &glBuffer); + glBindTexture(GL_TEXTURE_2D, glBuffer); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nScreenWidth, nScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pDefaultDrawTarget->GetData()); + + + // Create user resources as part of this thread + if (!OnUserCreate()) + bAtomActive = false; + + auto tp1 = std::chrono::system_clock::now(); + auto tp2 = std::chrono::system_clock::now(); + + while (bAtomActive) + { + // Run as fast as possible + while (bAtomActive) + { + // Handle Timing + tp2 = std::chrono::system_clock::now(); + std::chrono::duration elapsedTime = tp2 - tp1; + tp1 = tp2; + + // Our time per frame coefficient + float fElapsedTime = elapsedTime.count(); + +#ifndef _WIN32 + // Handle Xlib Message Loop - we do this in the + // same thread that OpenGL was created so we dont + // need to worry too much about multithreading with X11 + XEvent xev; + while (XPending(olc_Display)) + { + XNextEvent(olc_Display, &xev); + if (xev.type == Expose) + { + XWindowAttributes gwa; + XGetWindowAttributes(olc_Display, olc_Window, &gwa); + nWindowWidth = gwa.width; + nWindowHeight = gwa.height; + olc_UpdateViewport(); + glClear(GL_COLOR_BUFFER_BIT); // Thanks Benedani! + } + else if (xev.type == ConfigureNotify) + { + XConfigureEvent xce = xev.xconfigure; + nWindowWidth = xce.width; + nWindowHeight = xce.height; + } + else if (xev.type == KeyPress) + { + KeySym sym = XLookupKeysym(&xev.xkey, 0); + pKeyNewState[mapKeys[sym]] = true; + XKeyEvent *e = (XKeyEvent *)&xev; // Because DragonEye loves numpads + XLookupString(e, NULL, 0, &sym, NULL); + pKeyNewState[mapKeys[sym]] = true; + } + else if (xev.type == KeyRelease) + { + KeySym sym = XLookupKeysym(&xev.xkey, 0); + pKeyNewState[mapKeys[sym]] = false; + XKeyEvent *e = (XKeyEvent *)&xev; + XLookupString(e, NULL, 0, &sym, NULL); + pKeyNewState[mapKeys[sym]] = false; + } + else if (xev.type == ButtonPress) + { + switch (xev.xbutton.button) + { + case 1: pMouseNewState[0] = true; break; + case 2: pMouseNewState[2] = true; break; + case 3: pMouseNewState[1] = true; break; + case 4: olc_UpdateMouseWheel(120); break; + case 5: olc_UpdateMouseWheel(-120); break; + default: break; + } + } + else if (xev.type == ButtonRelease) + { + switch (xev.xbutton.button) + { + case 1: pMouseNewState[0] = false; break; + case 2: pMouseNewState[2] = false; break; + case 3: pMouseNewState[1] = false; break; + default: break; + } + } + else if (xev.type == MotionNotify) + { + olc_UpdateMouse(xev.xmotion.x, xev.xmotion.y); + } + else if (xev.type == FocusIn) + { + bHasInputFocus = true; + } + else if (xev.type == FocusOut) + { + bHasInputFocus = false; + } + else if (xev.type == ClientMessage) + { + bAtomActive = false; + } + } +#endif + + // Handle User Input - Keyboard + for (int i = 0; i < 256; i++) + { + pKeyboardState[i].bPressed = false; + pKeyboardState[i].bReleased = false; + + if (pKeyNewState[i] != pKeyOldState[i]) + { + if (pKeyNewState[i]) + { + pKeyboardState[i].bPressed = !pKeyboardState[i].bHeld; + pKeyboardState[i].bHeld = true; + } + else + { + pKeyboardState[i].bReleased = true; + pKeyboardState[i].bHeld = false; + } + } + + pKeyOldState[i] = pKeyNewState[i]; + } + + // Handle User Input - Mouse + for (int i = 0; i < 5; i++) + { + pMouseState[i].bPressed = false; + pMouseState[i].bReleased = false; + + if (pMouseNewState[i] != pMouseOldState[i]) + { + if (pMouseNewState[i]) + { + pMouseState[i].bPressed = !pMouseState[i].bHeld; + pMouseState[i].bHeld = true; + } + else + { + pMouseState[i].bReleased = true; + pMouseState[i].bHeld = false; + } + } + + pMouseOldState[i] = pMouseNewState[i]; + } + + // Cache mouse coordinates so they remain + // consistent during frame + nMousePosX = nMousePosXcache; + nMousePosY = nMousePosYcache; + + nMouseWheelDelta = nMouseWheelDeltaCache; + nMouseWheelDeltaCache = 0; + +#ifdef OLC_DBG_OVERDRAW + olc::Sprite::nOverdrawCount = 0; +#endif + + // Handle Frame Update + if (!OnUserUpdate(fElapsedTime)) + bAtomActive = false; + + // Display Graphics + glViewport(nViewX, nViewY, nViewW, nViewH); + + // TODO: This is a bit slow (especially in debug, but 100x faster in release mode???) + // Copy pixel array into texture + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nScreenWidth, nScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, pDefaultDrawTarget->GetData()); + + // Display texture on screen + glBegin(GL_QUADS); + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0f + (fSubPixelOffsetX), -1.0f + (fSubPixelOffsetY), 0.0f); + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0f + (fSubPixelOffsetX), 1.0f + (fSubPixelOffsetY), 0.0f); + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0f + (fSubPixelOffsetX), 1.0f + (fSubPixelOffsetY), 0.0f); + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0f + (fSubPixelOffsetX), -1.0f + (fSubPixelOffsetY), 0.0f); + glEnd(); + + // Present Graphics to screen +#ifdef _WIN32 + SwapBuffers(glDeviceContext); +#else + glXSwapBuffers(olc_Display, olc_Window); +#endif + + // Update Title Bar + fFrameTimer += fElapsedTime; + nFrameCount++; + if (fFrameTimer >= 1.0f) + { + fFrameTimer -= 1.0f; + + std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + " - FPS: " + std::to_string(nFrameCount); +#ifdef _WIN32 +#ifdef UNICODE + SetWindowText(olc_hWnd, ConvertS2W(sTitle).c_str()); +#else + SetWindowText(olc_hWnd, sTitle.c_str()); +#endif +#else + XStoreName(olc_Display, olc_Window, sTitle.c_str()); +#endif + nFrameCount = 0; + } + } + + // Allow the user to free resources if they have overrided the destroy function + if (OnUserDestroy()) + { + // User has permitted destroy, so exit and clean up + } + else + { + // User denied destroy for some reason, so continue running + bAtomActive = true; + } + } + +#ifdef _WIN32 + wglDeleteContext(glRenderContext); + PostMessage(olc_hWnd, WM_DESTROY, 0, 0); +#else + glXMakeCurrent(olc_Display, None, NULL); + glXDestroyContext(olc_Display, glDeviceContext); + XDestroyWindow(olc_Display, olc_Window); + XCloseDisplay(olc_Display); +#endif + + } + +#ifdef _WIN32 + // Thanks @MaGetzUb for this, which allows sprites to be defined + // at construction, by initialising the GDI subsystem + static class GDIPlusStartup + { + public: + GDIPlusStartup() + { + Gdiplus::GdiplusStartupInput startupInput; + ULONG_PTR token; + Gdiplus::GdiplusStartup(&token, &startupInput, NULL); + }; + } gdistartup; +#endif + + + void PixelGameEngine::olc_ConstructFontSheet() + { + std::string data; + data += "?Q`0001oOch0o01o@F40o000000000"; + data += "O000000nOT0063Qo4d8>?7a14Gno94AA4gno94AaOT0>o3`oO400o7QN00000400"; + data += "Of80001oOg<7O7moBGT7O7lABET024@aBEd714AiOdl717a_=TH013Q>00000000"; + data += "720D000V?V5oB3Q_HdUoE7a9@DdDE4A9@DmoE4A;Hg]oM4Aj8S4D84@`00000000"; + data += "OaPT1000Oa`^13P1@AI[?g`1@A=[OdAoHgljA4Ao?WlBA7l1710007l100000000"; + data += "ObM6000oOfMV?3QoBDD`O7a0BDDH@5A0BDD<@5A0BGeVO5ao@CQR?5Po00000000"; + data += "Oc``000?Ogij70PO2D]??0Ph2DUM@7i`2DTg@7lh2GUj?0TO0C1870T?00000000"; + data += "70<4001o?P<7?1QoHg43O;`h@GT0@:@LB@d0>:@hN@L0@?aoN@<0O7ao0000?000"; + data += "OcH0001SOglLA7mg24TnK7ln24US>0PL24U140PnOgl0>7QgOcH0K71S0000A000"; + data += "00H00000@Dm1S007@DUSg00?OdTnH7YhOfTL<7Yh@Cl0700?@Ah0300700000000"; + data += "<008001QL00ZA41a@6HnI<1i@FHLM81M@@0LG81?O`0nC?Y7?`0ZA7Y300080000"; + data += "O`082000Oh0827mo6>Hn?Wmo?6HnMb11MP08@C11H`08@FP0@@0004@000000000"; + data += "00P00001Oab00003OcKP0006@6=PMgl<@440MglH@000000`@000001P00000000"; + data += "Ob@8@@00Ob@8@Ga13R@8Mga172@8?PAo3R@827QoOb@820@0O`0007`0000007P0"; + data += "O`000P08Od400g`<3V=P0G`673IP0`@3>1`00P@6O`P00g`SetPixel(px, py, olc::Pixel(k, k, k, k)); + if (++py == 48) { px++; py = 0; } + } + } + } + +#ifdef _WIN32 + HWND PixelGameEngine::olc_WindowCreate() + { + WNDCLASS wc; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.hInstance = GetModuleHandle(nullptr); + wc.lpfnWndProc = olc_WindowEvent; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.lpszMenuName = nullptr; + wc.hbrBackground = nullptr; +#ifdef UNICODE + wc.lpszClassName = L"OLC_PIXEL_GAME_ENGINE"; +#else + wc.lpszClassName = "OLC_PIXEL_GAME_ENGINE"; +#endif + + RegisterClass(&wc); + + nWindowWidth = (LONG)nScreenWidth * (LONG)nPixelWidth; + nWindowHeight = (LONG)nScreenHeight * (LONG)nPixelHeight; + + // Define window furniture + DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dwStyle = WS_CAPTION | WS_SYSMENU | WS_VISIBLE;// | WS_THICKFRAME; + + int nCosmeticOffset = 30; + nViewW = nWindowWidth; + nViewH = nWindowHeight; + + // Handle Fullscreen + if (bFullScreen) + { + dwExStyle = 0; + dwStyle = WS_VISIBLE | WS_POPUP; + nCosmeticOffset = 0; + HMONITOR hmon = MonitorFromWindow(olc_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi = { sizeof(mi) }; + if (!GetMonitorInfo(hmon, &mi)) return NULL; + nWindowWidth = mi.rcMonitor.right; + nWindowHeight = mi.rcMonitor.bottom; + + + } + + olc_UpdateViewport(); + + // Keep client size as requested + RECT rWndRect = { 0, 0, nWindowWidth, nWindowHeight }; + AdjustWindowRectEx(&rWndRect, dwStyle, FALSE, dwExStyle); + int width = rWndRect.right - rWndRect.left; + int height = rWndRect.bottom - rWndRect.top; + +#ifdef UNICODE + olc_hWnd = CreateWindowEx(dwExStyle, L"OLC_PIXEL_GAME_ENGINE", L"", dwStyle, + nCosmeticOffset, nCosmeticOffset, width, height, NULL, NULL, GetModuleHandle(nullptr), this); +#else + olc_hWnd = CreateWindowEx(dwExStyle, "OLC_PIXEL_GAME_ENGINE", "", dwStyle, + nCosmeticOffset, nCosmeticOffset, width, height, NULL, NULL, GetModuleHandle(nullptr), this); +#endif + + // Create Keyboard Mapping + mapKeys[0x00] = Key::NONE; + mapKeys[0x41] = Key::A; mapKeys[0x42] = Key::B; mapKeys[0x43] = Key::C; mapKeys[0x44] = Key::D; mapKeys[0x45] = Key::E; + mapKeys[0x46] = Key::F; mapKeys[0x47] = Key::G; mapKeys[0x48] = Key::H; mapKeys[0x49] = Key::I; mapKeys[0x4A] = Key::J; + mapKeys[0x4B] = Key::K; mapKeys[0x4C] = Key::L; mapKeys[0x4D] = Key::M; mapKeys[0x4E] = Key::N; mapKeys[0x4F] = Key::O; + mapKeys[0x50] = Key::P; mapKeys[0x51] = Key::Q; mapKeys[0x52] = Key::R; mapKeys[0x53] = Key::S; mapKeys[0x54] = Key::T; + mapKeys[0x55] = Key::U; mapKeys[0x56] = Key::V; mapKeys[0x57] = Key::W; mapKeys[0x58] = Key::X; mapKeys[0x59] = Key::Y; + mapKeys[0x5A] = Key::Z; + + mapKeys[VK_F1] = Key::F1; mapKeys[VK_F2] = Key::F2; mapKeys[VK_F3] = Key::F3; mapKeys[VK_F4] = Key::F4; + mapKeys[VK_F5] = Key::F5; mapKeys[VK_F6] = Key::F6; mapKeys[VK_F7] = Key::F7; mapKeys[VK_F8] = Key::F8; + mapKeys[VK_F9] = Key::F9; mapKeys[VK_F10] = Key::F10; mapKeys[VK_F11] = Key::F11; mapKeys[VK_F12] = Key::F12; + + mapKeys[VK_DOWN] = Key::DOWN; mapKeys[VK_LEFT] = Key::LEFT; mapKeys[VK_RIGHT] = Key::RIGHT; mapKeys[VK_UP] = Key::UP; + mapKeys[VK_RETURN] = Key::ENTER; //mapKeys[VK_RETURN] = Key::RETURN; + + mapKeys[VK_BACK] = Key::BACK; mapKeys[VK_ESCAPE] = Key::ESCAPE; mapKeys[VK_RETURN] = Key::ENTER; mapKeys[VK_PAUSE] = Key::PAUSE; + mapKeys[VK_SCROLL] = Key::SCROLL; mapKeys[VK_TAB] = Key::TAB; mapKeys[VK_DELETE] = Key::DEL; mapKeys[VK_HOME] = Key::HOME; + mapKeys[VK_END] = Key::END; mapKeys[VK_PRIOR] = Key::PGUP; mapKeys[VK_NEXT] = Key::PGDN; mapKeys[VK_INSERT] = Key::INS; + mapKeys[VK_SHIFT] = Key::SHIFT; mapKeys[VK_CONTROL] = Key::CTRL; + mapKeys[VK_SPACE] = Key::SPACE; + + mapKeys[0x30] = Key::K0; mapKeys[0x31] = Key::K1; mapKeys[0x32] = Key::K2; mapKeys[0x33] = Key::K3; mapKeys[0x34] = Key::K4; + mapKeys[0x35] = Key::K5; mapKeys[0x36] = Key::K6; mapKeys[0x37] = Key::K7; mapKeys[0x38] = Key::K8; mapKeys[0x39] = Key::K9; + + mapKeys[VK_NUMPAD0] = Key::NP0; mapKeys[VK_NUMPAD1] = Key::NP1; mapKeys[VK_NUMPAD2] = Key::NP2; mapKeys[VK_NUMPAD3] = Key::NP3; mapKeys[VK_NUMPAD4] = Key::NP4; + mapKeys[VK_NUMPAD5] = Key::NP5; mapKeys[VK_NUMPAD6] = Key::NP6; mapKeys[VK_NUMPAD7] = Key::NP7; mapKeys[VK_NUMPAD8] = Key::NP8; mapKeys[VK_NUMPAD9] = Key::NP9; + mapKeys[VK_MULTIPLY] = Key::NP_MUL; mapKeys[VK_ADD] = Key::NP_ADD; mapKeys[VK_DIVIDE] = Key::NP_DIV; mapKeys[VK_SUBTRACT] = Key::NP_SUB; mapKeys[VK_DECIMAL] = Key::NP_DECIMAL; + + return olc_hWnd; + } + + bool PixelGameEngine::olc_OpenGLCreate() + { + // Create Device Context + glDeviceContext = GetDC(olc_hWnd); + PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + PFD_MAIN_PLANE, 0, 0, 0, 0 + }; + + int pf = 0; + if (!(pf = ChoosePixelFormat(glDeviceContext, &pfd))) return false; + SetPixelFormat(glDeviceContext, pf, &pfd); + + if (!(glRenderContext = wglCreateContext(glDeviceContext))) return false; + wglMakeCurrent(glDeviceContext, glRenderContext); + + glViewport(nViewX, nViewY, nViewW, nViewH); + + // Remove Frame cap + wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT"); + if (wglSwapInterval) wglSwapInterval(0); + return true; + } + + // Windows Event Handler + LRESULT CALLBACK PixelGameEngine::olc_WindowEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + static PixelGameEngine *sge; + switch (uMsg) + { + case WM_CREATE: sge = (PixelGameEngine*)((LPCREATESTRUCT)lParam)->lpCreateParams; return 0; + case WM_MOUSEMOVE: + { + uint16_t x = lParam & 0xFFFF; // Thanks @ForAbby (Discord) + uint16_t y = (lParam >> 16) & 0xFFFF; + int16_t ix = *(int16_t*)&x; + int16_t iy = *(int16_t*)&y; + sge->olc_UpdateMouse(ix, iy); + return 0; + } + case WM_SIZE: + { + sge->olc_UpdateWindowSize(lParam & 0xFFFF, (lParam >> 16) & 0xFFFF); + return 0; + } + case WM_MOUSEWHEEL: + { + sge->olc_UpdateMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam)); + return 0; + } + case WM_MOUSELEAVE: sge->bHasMouseFocus = false; return 0; + case WM_SETFOCUS: sge->bHasInputFocus = true; return 0; + case WM_KILLFOCUS: sge->bHasInputFocus = false; return 0; + case WM_KEYDOWN: sge->pKeyNewState[mapKeys[wParam]] = true; return 0; + case WM_KEYUP: sge->pKeyNewState[mapKeys[wParam]] = false; return 0; + case WM_LBUTTONDOWN:sge->pMouseNewState[0] = true; return 0; + case WM_LBUTTONUP: sge->pMouseNewState[0] = false; return 0; + case WM_RBUTTONDOWN:sge->pMouseNewState[1] = true; return 0; + case WM_RBUTTONUP: sge->pMouseNewState[1] = false; return 0; + case WM_MBUTTONDOWN:sge->pMouseNewState[2] = true; return 0; + case WM_MBUTTONUP: sge->pMouseNewState[2] = false; return 0; + case WM_CLOSE: bAtomActive = false; return 0; + case WM_DESTROY: PostQuitMessage(0); return 0; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } +#else + // Do the Linux stuff! + Display* PixelGameEngine::olc_WindowCreate() + { + XInitThreads(); + + // Grab the deafult display and window + olc_Display = XOpenDisplay(NULL); + olc_WindowRoot = DefaultRootWindow(olc_Display); + + // Based on the display capabilities, configure the appearance of the window + GLint olc_GLAttribs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; + olc_VisualInfo = glXChooseVisual(olc_Display, 0, olc_GLAttribs); + olc_ColourMap = XCreateColormap(olc_Display, olc_WindowRoot, olc_VisualInfo->visual, AllocNone); + olc_SetWindowAttribs.colormap = olc_ColourMap; + + // Register which events we are interested in receiving + olc_SetWindowAttribs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | StructureNotifyMask; + + // Create the window + olc_Window = XCreateWindow(olc_Display, olc_WindowRoot, 30, 30, nScreenWidth * nPixelWidth, nScreenHeight * nPixelHeight, 0, olc_VisualInfo->depth, InputOutput, olc_VisualInfo->visual, CWColormap | CWEventMask, &olc_SetWindowAttribs); + + Atom wmDelete = XInternAtom(olc_Display, "WM_DELETE_WINDOW", true); + XSetWMProtocols(olc_Display, olc_Window, &wmDelete, 1); + + XMapWindow(olc_Display, olc_Window); + XStoreName(olc_Display, olc_Window, "OneLoneCoder.com - Pixel Game Engine"); + + if (bFullScreen) // Thanks DragonEye, again :D + { + Atom wm_state; + Atom fullscreen; + wm_state = XInternAtom(olc_Display, "_NET_WM_STATE", False); + fullscreen = XInternAtom(olc_Display, "_NET_WM_STATE_FULLSCREEN", False); + XEvent xev{ 0 }; + xev.type = ClientMessage; + xev.xclient.window = olc_Window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = (bFullScreen ? 1 : 0); // the action (0: off, 1: on, 2: toggle) + xev.xclient.data.l[1] = fullscreen; // first property to alter + xev.xclient.data.l[2] = 0; // second property to alter + xev.xclient.data.l[3] = 0; // source indication + XMapWindow(olc_Display, olc_Window); + XSendEvent(olc_Display, DefaultRootWindow(olc_Display), False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + XFlush(olc_Display); + XWindowAttributes gwa; + XGetWindowAttributes(olc_Display, olc_Window, &gwa); + nWindowWidth = gwa.width; + nWindowHeight = gwa.height; + olc_UpdateViewport(); + } + + // Create Keyboard Mapping + mapKeys[0x00] = Key::NONE; + mapKeys[0x61] = Key::A; mapKeys[0x62] = Key::B; mapKeys[0x63] = Key::C; mapKeys[0x64] = Key::D; mapKeys[0x65] = Key::E; + mapKeys[0x66] = Key::F; mapKeys[0x67] = Key::G; mapKeys[0x68] = Key::H; mapKeys[0x69] = Key::I; mapKeys[0x6A] = Key::J; + mapKeys[0x6B] = Key::K; mapKeys[0x6C] = Key::L; mapKeys[0x6D] = Key::M; mapKeys[0x6E] = Key::N; mapKeys[0x6F] = Key::O; + mapKeys[0x70] = Key::P; mapKeys[0x71] = Key::Q; mapKeys[0x72] = Key::R; mapKeys[0x73] = Key::S; mapKeys[0x74] = Key::T; + mapKeys[0x75] = Key::U; mapKeys[0x76] = Key::V; mapKeys[0x77] = Key::W; mapKeys[0x78] = Key::X; mapKeys[0x79] = Key::Y; + mapKeys[0x7A] = Key::Z; + + mapKeys[XK_F1] = Key::F1; mapKeys[XK_F2] = Key::F2; mapKeys[XK_F3] = Key::F3; mapKeys[XK_F4] = Key::F4; + mapKeys[XK_F5] = Key::F5; mapKeys[XK_F6] = Key::F6; mapKeys[XK_F7] = Key::F7; mapKeys[XK_F8] = Key::F8; + mapKeys[XK_F9] = Key::F9; mapKeys[XK_F10] = Key::F10; mapKeys[XK_F11] = Key::F11; mapKeys[XK_F12] = Key::F12; + + mapKeys[XK_Down] = Key::DOWN; mapKeys[XK_Left] = Key::LEFT; mapKeys[XK_Right] = Key::RIGHT; mapKeys[XK_Up] = Key::UP; + mapKeys[XK_KP_Enter] = Key::ENTER; mapKeys[XK_Return] = Key::ENTER; + + mapKeys[XK_BackSpace] = Key::BACK; mapKeys[XK_Escape] = Key::ESCAPE; mapKeys[XK_Linefeed] = Key::ENTER; mapKeys[XK_Pause] = Key::PAUSE; + mapKeys[XK_Scroll_Lock] = Key::SCROLL; mapKeys[XK_Tab] = Key::TAB; mapKeys[XK_Delete] = Key::DEL; mapKeys[XK_Home] = Key::HOME; + mapKeys[XK_End] = Key::END; mapKeys[XK_Page_Up] = Key::PGUP; mapKeys[XK_Page_Down] = Key::PGDN; mapKeys[XK_Insert] = Key::INS; + mapKeys[XK_Shift_L] = Key::SHIFT; mapKeys[XK_Shift_R] = Key::SHIFT; mapKeys[XK_Control_L] = Key::CTRL; mapKeys[XK_Control_R] = Key::CTRL; + mapKeys[XK_space] = Key::SPACE; + + mapKeys[XK_0] = Key::K0; mapKeys[XK_1] = Key::K1; mapKeys[XK_2] = Key::K2; mapKeys[XK_3] = Key::K3; mapKeys[XK_4] = Key::K4; + mapKeys[XK_5] = Key::K5; mapKeys[XK_6] = Key::K6; mapKeys[XK_7] = Key::K7; mapKeys[XK_8] = Key::K8; mapKeys[XK_9] = Key::K9; + + mapKeys[XK_KP_0] = Key::NP0; mapKeys[XK_KP_1] = Key::NP1; mapKeys[XK_KP_2] = Key::NP2; mapKeys[XK_KP_3] = Key::NP3; mapKeys[XK_KP_4] = Key::NP4; + mapKeys[XK_KP_5] = Key::NP5; mapKeys[XK_KP_6] = Key::NP6; mapKeys[XK_KP_7] = Key::NP7; mapKeys[XK_KP_8] = Key::NP8; mapKeys[XK_KP_9] = Key::NP9; + mapKeys[XK_KP_Multiply] = Key::NP_MUL; mapKeys[XK_KP_Add] = Key::NP_ADD; mapKeys[XK_KP_Divide] = Key::NP_DIV; mapKeys[XK_KP_Subtract] = Key::NP_SUB; mapKeys[XK_KP_Decimal] = Key::NP_DECIMAL; + + return olc_Display; + } + + bool PixelGameEngine::olc_OpenGLCreate() + { + glDeviceContext = glXCreateContext(olc_Display, olc_VisualInfo, nullptr, GL_TRUE); + glXMakeCurrent(olc_Display, olc_Window, glDeviceContext); + + XWindowAttributes gwa; + XGetWindowAttributes(olc_Display, olc_Window, &gwa); + glViewport(0, 0, gwa.width, gwa.height); + + glSwapIntervalEXT = nullptr; + glSwapIntervalEXT = (glSwapInterval_t*)glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"); + if (glSwapIntervalEXT) + glSwapIntervalEXT(olc_Display, olc_Window, 0); + else + { + printf("NOTE: Could not disable VSYNC, glXSwapIntervalEXT() was not found!\n"); + printf(" Don't worry though, things will still work, it's just the\n"); + printf(" frame rate will be capped to your monitors refresh rate - javidx9\n"); + } + + return true; + } + +#endif + + // Need a couple of statics as these are singleton instances + // read from multiple locations + std::atomic PixelGameEngine::bAtomActive{ false }; + std::map PixelGameEngine::mapKeys; + olc::PixelGameEngine* olc::PGEX::pge = nullptr; +#ifdef OLC_DBG_OVERDRAW + int olc::Sprite::nOverdrawCount = 0; +#endif + //============================================================= +} + +#endif