Initial commit
3
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
405
.idea/dbnavigator.xml
generated
Normal file
@@ -0,0 +1,405 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DBNavigator.Project.DatabaseFileManager">
|
||||
<open-files />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.Settings">
|
||||
<connections />
|
||||
<browser-settings>
|
||||
<general>
|
||||
<display-mode value="TABBED" />
|
||||
<navigation-history-size value="100" />
|
||||
<show-object-details value="false" />
|
||||
</general>
|
||||
<filters>
|
||||
<object-type-filter>
|
||||
<object-type name="SCHEMA" enabled="true" />
|
||||
<object-type name="USER" enabled="true" />
|
||||
<object-type name="ROLE" enabled="true" />
|
||||
<object-type name="PRIVILEGE" enabled="true" />
|
||||
<object-type name="CHARSET" enabled="true" />
|
||||
<object-type name="TABLE" enabled="true" />
|
||||
<object-type name="VIEW" enabled="true" />
|
||||
<object-type name="MATERIALIZED_VIEW" enabled="true" />
|
||||
<object-type name="NESTED_TABLE" enabled="true" />
|
||||
<object-type name="COLUMN" enabled="true" />
|
||||
<object-type name="INDEX" enabled="true" />
|
||||
<object-type name="CONSTRAINT" enabled="true" />
|
||||
<object-type name="DATASET_TRIGGER" enabled="true" />
|
||||
<object-type name="DATABASE_TRIGGER" enabled="true" />
|
||||
<object-type name="SYNONYM" enabled="true" />
|
||||
<object-type name="SEQUENCE" enabled="true" />
|
||||
<object-type name="PROCEDURE" enabled="true" />
|
||||
<object-type name="FUNCTION" enabled="true" />
|
||||
<object-type name="PACKAGE" enabled="true" />
|
||||
<object-type name="TYPE" enabled="true" />
|
||||
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
|
||||
<object-type name="ARGUMENT" enabled="true" />
|
||||
<object-type name="DIMENSION" enabled="true" />
|
||||
<object-type name="CLUSTER" enabled="true" />
|
||||
<object-type name="DBLINK" enabled="true" />
|
||||
</object-type-filter>
|
||||
</filters>
|
||||
<sorting>
|
||||
<object-type name="COLUMN" sorting-type="NAME" />
|
||||
<object-type name="FUNCTION" sorting-type="NAME" />
|
||||
<object-type name="PROCEDURE" sorting-type="NAME" />
|
||||
<object-type name="ARGUMENT" sorting-type="POSITION" />
|
||||
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
|
||||
</sorting>
|
||||
<default-editors>
|
||||
<object-type name="VIEW" editor-type="SELECTION" />
|
||||
<object-type name="PACKAGE" editor-type="SELECTION" />
|
||||
<object-type name="TYPE" editor-type="SELECTION" />
|
||||
</default-editors>
|
||||
</browser-settings>
|
||||
<navigation-settings>
|
||||
<lookup-filters>
|
||||
<lookup-objects>
|
||||
<object-type name="SCHEMA" enabled="true" />
|
||||
<object-type name="USER" enabled="false" />
|
||||
<object-type name="ROLE" enabled="false" />
|
||||
<object-type name="PRIVILEGE" enabled="false" />
|
||||
<object-type name="CHARSET" enabled="false" />
|
||||
<object-type name="TABLE" enabled="true" />
|
||||
<object-type name="VIEW" enabled="true" />
|
||||
<object-type name="MATERIALIZED VIEW" enabled="true" />
|
||||
<object-type name="INDEX" enabled="true" />
|
||||
<object-type name="CONSTRAINT" enabled="true" />
|
||||
<object-type name="DATASET TRIGGER" enabled="true" />
|
||||
<object-type name="DATABASE TRIGGER" enabled="true" />
|
||||
<object-type name="SYNONYM" enabled="false" />
|
||||
<object-type name="SEQUENCE" enabled="true" />
|
||||
<object-type name="PROCEDURE" enabled="true" />
|
||||
<object-type name="FUNCTION" enabled="true" />
|
||||
<object-type name="PACKAGE" enabled="true" />
|
||||
<object-type name="TYPE" enabled="true" />
|
||||
<object-type name="DIMENSION" enabled="false" />
|
||||
<object-type name="CLUSTER" enabled="false" />
|
||||
<object-type name="DBLINK" enabled="true" />
|
||||
</lookup-objects>
|
||||
<force-database-load value="false" />
|
||||
<prompt-connection-selection value="true" />
|
||||
<prompt-schema-selection value="true" />
|
||||
</lookup-filters>
|
||||
</navigation-settings>
|
||||
<dataset-grid-settings>
|
||||
<general>
|
||||
<enable-zooming value="true" />
|
||||
<enable-column-tooltip value="true" />
|
||||
</general>
|
||||
<sorting>
|
||||
<nulls-first value="true" />
|
||||
<max-sorting-columns value="4" />
|
||||
</sorting>
|
||||
<audit-columns>
|
||||
<column-names value="" />
|
||||
<visible value="true" />
|
||||
<editable value="false" />
|
||||
</audit-columns>
|
||||
</dataset-grid-settings>
|
||||
<dataset-editor-settings>
|
||||
<text-editor-popup>
|
||||
<active value="false" />
|
||||
<active-if-empty value="false" />
|
||||
<data-length-threshold value="100" />
|
||||
<popup-delay value="1000" />
|
||||
</text-editor-popup>
|
||||
<values-actions-popup>
|
||||
<show-popup-button value="true" />
|
||||
<element-count-threshold value="1000" />
|
||||
<data-length-threshold value="250" />
|
||||
</values-actions-popup>
|
||||
<general>
|
||||
<fetch-block-size value="100" />
|
||||
<fetch-timeout value="30" />
|
||||
<trim-whitespaces value="true" />
|
||||
<convert-empty-strings-to-null value="true" />
|
||||
<select-content-on-cell-edit value="true" />
|
||||
<large-value-preview-active value="true" />
|
||||
</general>
|
||||
<filters>
|
||||
<prompt-filter-dialog value="true" />
|
||||
<default-filter-type value="BASIC" />
|
||||
</filters>
|
||||
<qualified-text-editor text-length-threshold="300">
|
||||
<content-types>
|
||||
<content-type name="Text" enabled="true" />
|
||||
<content-type name="Properties" enabled="true" />
|
||||
<content-type name="XML" enabled="true" />
|
||||
<content-type name="DTD" enabled="true" />
|
||||
<content-type name="HTML" enabled="true" />
|
||||
<content-type name="XHTML" enabled="true" />
|
||||
<content-type name="Java" enabled="true" />
|
||||
<content-type name="SQL" enabled="true" />
|
||||
<content-type name="PL/SQL" enabled="true" />
|
||||
<content-type name="JSON" enabled="true" />
|
||||
<content-type name="JSON5" enabled="true" />
|
||||
<content-type name="Groovy" enabled="true" />
|
||||
<content-type name="YAML" enabled="true" />
|
||||
<content-type name="Manifest" enabled="true" />
|
||||
</content-types>
|
||||
</qualified-text-editor>
|
||||
<record-navigation>
|
||||
<navigation-target value="VIEWER" />
|
||||
</record-navigation>
|
||||
</dataset-editor-settings>
|
||||
<code-editor-settings>
|
||||
<general>
|
||||
<show-object-navigation-gutter value="false" />
|
||||
<show-spec-declaration-navigation-gutter value="true" />
|
||||
<enable-spellchecking value="true" />
|
||||
<enable-reference-spellchecking value="false" />
|
||||
</general>
|
||||
<confirmations>
|
||||
<save-changes value="false" />
|
||||
<revert-changes value="true" />
|
||||
<exit-on-changes value="ASK" />
|
||||
</confirmations>
|
||||
</code-editor-settings>
|
||||
<code-completion-settings>
|
||||
<filters>
|
||||
<basic-filter>
|
||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||
<filter-element type="OBJECT" id="role" selected="true" />
|
||||
<filter-element type="OBJECT" id="user" selected="true" />
|
||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||
<user-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</user-schema>
|
||||
<public-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="false" />
|
||||
<filter-element type="OBJECT" id="view" selected="false" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="false" />
|
||||
<filter-element type="OBJECT" id="index" selected="false" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="false" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="false" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="false" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="false" />
|
||||
<filter-element type="OBJECT" id="function" selected="false" />
|
||||
<filter-element type="OBJECT" id="package" selected="false" />
|
||||
<filter-element type="OBJECT" id="type" selected="false" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="false" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="false" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="false" />
|
||||
</public-schema>
|
||||
<any-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</any-schema>
|
||||
</basic-filter>
|
||||
<extended-filter>
|
||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||
<filter-element type="OBJECT" id="user" selected="true" />
|
||||
<filter-element type="OBJECT" id="role" selected="true" />
|
||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||
<user-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</user-schema>
|
||||
<public-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</public-schema>
|
||||
<any-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</any-schema>
|
||||
</extended-filter>
|
||||
</filters>
|
||||
<sorting enabled="true">
|
||||
<sorting-element type="RESERVED_WORD" id="keyword" />
|
||||
<sorting-element type="RESERVED_WORD" id="datatype" />
|
||||
<sorting-element type="OBJECT" id="column" />
|
||||
<sorting-element type="OBJECT" id="table" />
|
||||
<sorting-element type="OBJECT" id="view" />
|
||||
<sorting-element type="OBJECT" id="materialized view" />
|
||||
<sorting-element type="OBJECT" id="index" />
|
||||
<sorting-element type="OBJECT" id="constraint" />
|
||||
<sorting-element type="OBJECT" id="trigger" />
|
||||
<sorting-element type="OBJECT" id="synonym" />
|
||||
<sorting-element type="OBJECT" id="sequence" />
|
||||
<sorting-element type="OBJECT" id="procedure" />
|
||||
<sorting-element type="OBJECT" id="function" />
|
||||
<sorting-element type="OBJECT" id="package" />
|
||||
<sorting-element type="OBJECT" id="type" />
|
||||
<sorting-element type="OBJECT" id="dimension" />
|
||||
<sorting-element type="OBJECT" id="cluster" />
|
||||
<sorting-element type="OBJECT" id="dblink" />
|
||||
<sorting-element type="OBJECT" id="schema" />
|
||||
<sorting-element type="OBJECT" id="role" />
|
||||
<sorting-element type="OBJECT" id="user" />
|
||||
<sorting-element type="RESERVED_WORD" id="function" />
|
||||
<sorting-element type="RESERVED_WORD" id="parameter" />
|
||||
</sorting>
|
||||
<format>
|
||||
<enforce-code-style-case value="true" />
|
||||
</format>
|
||||
</code-completion-settings>
|
||||
<execution-engine-settings>
|
||||
<statement-execution>
|
||||
<fetch-block-size value="100" />
|
||||
<execution-timeout value="20" />
|
||||
<debug-execution-timeout value="600" />
|
||||
<focus-result value="false" />
|
||||
<prompt-execution value="false" />
|
||||
</statement-execution>
|
||||
<script-execution>
|
||||
<command-line-interfaces />
|
||||
<execution-timeout value="300" />
|
||||
</script-execution>
|
||||
<method-execution>
|
||||
<execution-timeout value="30" />
|
||||
<debug-execution-timeout value="600" />
|
||||
<parameter-history-size value="10" />
|
||||
</method-execution>
|
||||
</execution-engine-settings>
|
||||
<operation-settings>
|
||||
<transactions>
|
||||
<uncommitted-changes>
|
||||
<on-project-close value="ASK" />
|
||||
<on-disconnect value="ASK" />
|
||||
<on-autocommit-toggle value="ASK" />
|
||||
</uncommitted-changes>
|
||||
<multiple-uncommitted-changes>
|
||||
<on-commit value="ASK" />
|
||||
<on-rollback value="ASK" />
|
||||
</multiple-uncommitted-changes>
|
||||
</transactions>
|
||||
<session-browser>
|
||||
<disconnect-session value="ASK" />
|
||||
<kill-session value="ASK" />
|
||||
<reload-on-filter-change value="false" />
|
||||
</session-browser>
|
||||
<compiler>
|
||||
<compile-type value="KEEP" />
|
||||
<compile-dependencies value="ASK" />
|
||||
<always-show-controls value="false" />
|
||||
</compiler>
|
||||
<debugger>
|
||||
<debugger-type value="ASK" />
|
||||
</debugger>
|
||||
</operation-settings>
|
||||
<ddl-file-settings>
|
||||
<extensions>
|
||||
<mapping file-type-id="VIEW" extensions="vw" />
|
||||
<mapping file-type-id="TRIGGER" extensions="trg" />
|
||||
<mapping file-type-id="PROCEDURE" extensions="prc" />
|
||||
<mapping file-type-id="FUNCTION" extensions="fnc" />
|
||||
<mapping file-type-id="PACKAGE" extensions="pkg" />
|
||||
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
|
||||
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
|
||||
<mapping file-type-id="TYPE" extensions="tpe" />
|
||||
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
|
||||
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
|
||||
</extensions>
|
||||
<general>
|
||||
<lookup-ddl-files value="true" />
|
||||
<create-ddl-files value="false" />
|
||||
<synchronize-ddl-files value="true" />
|
||||
<use-qualified-names value="false" />
|
||||
<make-scripts-rerunnable value="true" />
|
||||
</general>
|
||||
</ddl-file-settings>
|
||||
<general-settings>
|
||||
<regional-settings>
|
||||
<date-format value="MEDIUM" />
|
||||
<number-format value="UNGROUPED" />
|
||||
<locale value="SYSTEM_DEFAULT" />
|
||||
<use-custom-formats value="false" />
|
||||
</regional-settings>
|
||||
<environment>
|
||||
<environment-types>
|
||||
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
|
||||
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
|
||||
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
|
||||
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
|
||||
</environment-types>
|
||||
<visibility-settings>
|
||||
<connection-tabs value="true" />
|
||||
<dialog-headers value="true" />
|
||||
<object-editor-tabs value="true" />
|
||||
<script-editor-tabs value="false" />
|
||||
<execution-result-tabs value="true" />
|
||||
</visibility-settings>
|
||||
</environment>
|
||||
</general-settings>
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myValues">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="COLOR" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myCustomValuesEnabled" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Docker-404-games.iml" filepath="$PROJECT_DIR$/Docker-404-games.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
28
404_games/index.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>ups.. Page not Found !!! 404-Alarm!!!!</TITLE>
|
||||
</HEAD>
|
||||
<body>
|
||||
<center>
|
||||
<H1><b><FONT COLOR="#FF0000"><big><big>404 - Alert</big></big></FONT></b></H1>
|
||||
<H2>... page not found ...</H2>
|
||||
|
||||
<iframe id='404-game' width="520" height="520" scrolling="none" frameborder="0"></iframe>
|
||||
|
||||
<script>
|
||||
var randomBetween = function(f, to){
|
||||
return Math.floor(Math.random() * to) + f;
|
||||
}
|
||||
var randomGame = function(){
|
||||
var games = ["pacman", "space-invaders", "snake"];
|
||||
var randomGame = randomBetween(0,games.length);
|
||||
return games[randomGame];
|
||||
}
|
||||
var src = "" + randomGame();
|
||||
document.getElementById('404-game').src = src;
|
||||
</script>
|
||||
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
BIN
404_games/pacman/data/map.png
Normal file
|
After Width: | Height: | Size: 217 B |
BIN
404_games/pacman/images/32_dot.png
Normal file
|
After Width: | Height: | Size: 564 B |
BIN
404_games/pacman/images/32_player_close.png
Normal file
|
After Width: | Height: | Size: 583 B |
BIN
404_games/pacman/images/32_player_open.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
404_games/pacman/images/bg_center.png
Normal file
|
After Width: | Height: | Size: 898 B |
BIN
404_games/pacman/images/bg_down.png
Normal file
|
After Width: | Height: | Size: 902 B |
BIN
404_games/pacman/images/bg_left.png
Normal file
|
After Width: | Height: | Size: 775 B |
BIN
404_games/pacman/images/bg_right.png
Normal file
|
After Width: | Height: | Size: 765 B |
BIN
404_games/pacman/images/bg_up.png
Normal file
|
After Width: | Height: | Size: 904 B |
BIN
404_games/pacman/images/enemy_red.png
Normal file
|
After Width: | Height: | Size: 294 B |
23
404_games/pacman/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 Pacman</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id='canvas' height="480" width="512"></canvas>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/collision.js"></script>
|
||||
|
||||
<script src="js/assets.js"></script>
|
||||
<script src="js/draw.js"></script>
|
||||
<script src="js/update.js"></script>
|
||||
<script src="js/controls.js"></script>
|
||||
<script src="js/objects.js"></script>
|
||||
<script src="js/objectsLoad.js"></script>
|
||||
|
||||
<script src="js/ai.js"></script>
|
||||
|
||||
<script src="js/game.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
23
404_games/pacman/js/ai.js
Normal file
@@ -0,0 +1,23 @@
|
||||
var updateEnemies = function(modifier){
|
||||
|
||||
for (var i= 0; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
if (isCollidingBlocks(enemy,enemy.direction)){
|
||||
changeDirection(enemy);
|
||||
|
||||
} else {
|
||||
move(enemy, modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var changeDirection = function(enemy){
|
||||
var tol = p(-5,0);
|
||||
var randomDirection = randomBetween(0, 3);
|
||||
switch(randomDirection){
|
||||
case 0: if (!isCollidingBlocks(enemy, LEFT, tol)) enemy.direction = LEFT;break;
|
||||
case 1: if (!isCollidingBlocks(enemy, RIGHT, tol)) enemy.direction = RIGHT;break;
|
||||
case 2: if (!isCollidingBlocks(enemy, UP, tol)) enemy.direction = UP;break;
|
||||
default: if (!isCollidingBlocks(enemy, DOWN, tol)) enemy.direction = DOWN;break;
|
||||
}
|
||||
}
|
||||
20
404_games/pacman/js/assets.js
Normal file
@@ -0,0 +1,20 @@
|
||||
var setImage = function(img){
|
||||
var i = new Image();
|
||||
i.src = img;
|
||||
return i;
|
||||
};
|
||||
|
||||
// Hero image
|
||||
var playerImageClose = setImage("images/32_player_close.png");
|
||||
var playerImageOpen = setImage("images/32_player_open.png");
|
||||
|
||||
var monsterImage = setImage("images/enemy_red.png");
|
||||
|
||||
var dotImage = setImage("images/32_dot.png");
|
||||
|
||||
var backgroundImage = {};
|
||||
backgroundImage.center = setImage("images/bg_center.png");
|
||||
backgroundImage.left = setImage("images/bg_left.png");
|
||||
backgroundImage.right = setImage("images/bg_right.png");
|
||||
backgroundImage.down = setImage("images/bg_down.png");
|
||||
backgroundImage.up = setImage("images/bg_up.png");
|
||||
71
404_games/pacman/js/collision.js
Normal file
@@ -0,0 +1,71 @@
|
||||
//http://gamedev.stackexchange.com/questions/13774/how-do-i-detect-the-direction-of-2d-rectangular-object-collisions
|
||||
var collision = new Collision();
|
||||
|
||||
var RIGHT = { x: 1, y: 0};
|
||||
var LEFT = { x: -1, y: 0};
|
||||
var UP = { x: 0, y: -1};
|
||||
var DOWN = { x: 0, y: 1};
|
||||
|
||||
function Collision(){
|
||||
|
||||
this.onCollisionChange = function(ojb1, obj2, size, callback) {
|
||||
var isColliding = false;
|
||||
setInterval(
|
||||
function(){
|
||||
var beforeStatus = isColliding;
|
||||
isColliding = collision(obj1, obj2, size);
|
||||
if (beforeStatus != isColliding) callback();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
this.isCollidingDirection = function(obj1, obj2, direction, offset){
|
||||
switch(direction){
|
||||
case LEFT: return collision.containsLeft(obj1, obj2, SIZE, offset); break;
|
||||
case RIGHT: return collision.containsRight(obj1, obj2, SIZE, offset); break;
|
||||
case UP: return collision.containsUp(obj1, obj2, SIZE, offset); break;
|
||||
case DOWN: return collision.containsDown(obj1, obj2, SIZE, offset); break;
|
||||
default: console.log("Undefined direction");
|
||||
}
|
||||
}
|
||||
|
||||
this.contains = function(obj, p, size){
|
||||
var contains = p.x > obj.x && p.x < (obj.x + size) &&
|
||||
p.y > obj.y && p.y < (obj.y + size);
|
||||
return contains;
|
||||
}
|
||||
|
||||
this.collision = function(obj1, obj2, size){
|
||||
return obj1.x <= (obj2.x + size)
|
||||
&& obj2.x <= (obj1.x + size)
|
||||
&& obj1.y <= (obj2.y + size)
|
||||
&& obj2.y <= (obj1.y + size)
|
||||
}
|
||||
|
||||
this.containsLeft = function(obj1, obj2, size, offset){
|
||||
return this.contains(obj1, addCoords(middlePoints(obj2, size).left, offset) , size);
|
||||
}
|
||||
this.containsRight = function(obj1, obj2, size, offset){
|
||||
return this.contains(obj1, addCoords(middlePoints(obj2, size).right, offset), size);
|
||||
}
|
||||
this.containsUp = function(obj1, obj2, size, offset){
|
||||
return this.contains(obj1, addCoords(middlePoints(obj2, size).top, offset), size);
|
||||
}
|
||||
this.containsDown = function(obj1, obj2, size, offset){
|
||||
return this.contains(obj1, addCoords( middlePoints(obj2, size).bottom, offset), size);
|
||||
}
|
||||
|
||||
var addCoords = function(point, offset) {
|
||||
return p(point.x + offset.x, point.y + offset.y);
|
||||
}
|
||||
|
||||
var middlePoints = function(obj, size){
|
||||
var middleX = (obj.x + obj.x + size) / 2; //(obj.x *2 + size) / 2; ?
|
||||
var middleY = (obj.y + obj.y + size) / 2;
|
||||
return {
|
||||
left: p(obj.x, middleY),
|
||||
right: p(obj.x + size , middleY),
|
||||
top: p(middleX, obj.y),
|
||||
bottom: p(middleX, obj.y + size),
|
||||
}
|
||||
}
|
||||
}
|
||||
21
404_games/pacman/js/controls.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// Handle keyboard controls
|
||||
var keysDown = {};
|
||||
|
||||
var KEY_UP =38, KEY_DOWN =40, KEY_LEFT =37, KEY_RIGHT =39;
|
||||
|
||||
addEventListener("keydown", function (e) {
|
||||
keysDown[e.keyCode] = true;
|
||||
}, false);
|
||||
|
||||
addEventListener("keyup", function (e) {
|
||||
delete keysDown[e.keyCode];
|
||||
}, false);
|
||||
|
||||
|
||||
//Called from update.js
|
||||
var controls = function(modifier){
|
||||
if (KEY_LEFT in keysDown && !isCollidingBlocks(player, LEFT, p(-5,0))) player.direction = LEFT;
|
||||
if (KEY_RIGHT in keysDown && !isCollidingBlocks(player,RIGHT, p(5,0))) player.direction = RIGHT;
|
||||
if (KEY_UP in keysDown && !isCollidingBlocks(player,UP, p(0,-5))) player.direction = UP;
|
||||
if (KEY_DOWN in keysDown && !isCollidingBlocks(player,DOWN, p(0,5))) player.direction = DOWN;
|
||||
}
|
||||
87
404_games/pacman/js/draw.js
Normal file
@@ -0,0 +1,87 @@
|
||||
// Create the canvas
|
||||
var canvas = document.getElementById("canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
var SIZE = 32;
|
||||
|
||||
var directionToRotation = function(direction){
|
||||
switch(direction){
|
||||
case RIGHT : return 0;
|
||||
case LEFT: return 180;
|
||||
case DOWN: return 90;
|
||||
case UP: return 270;
|
||||
|
||||
}
|
||||
}
|
||||
// Draw everything
|
||||
var render = function () {
|
||||
// ctx.clearRect(0,0,canvas.width,canvas.height);
|
||||
/*
|
||||
if (bgReady) {
|
||||
ctx.drawImage(bgImage,0 , 0);
|
||||
}*/
|
||||
ctx.fillStyle="black";
|
||||
ctx.fillRect(0,0,canvas.width,canvas.height);
|
||||
|
||||
drawBackground();
|
||||
|
||||
if (!player.dead) {
|
||||
var image;
|
||||
if(player.sprite == 0) image = playerImageClose;
|
||||
else image = playerImageOpen;
|
||||
//TODO rotate with direction
|
||||
// ctx.drawImage(image, player.x, player.y, SIZE, SIZE);
|
||||
var rotation = directionToRotation(player.direction);
|
||||
drawRotated(image, player.x, player.y, rotation);
|
||||
}
|
||||
|
||||
for (var i=0; i < dots.length; i++){
|
||||
var dot = dots[i];
|
||||
ctx.drawImage(dotImage, dot.x, dot.y ,SIZE, SIZE);
|
||||
}
|
||||
|
||||
for (var i=0; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
ctx.drawImage(monsterImage, enemy.x, enemy.y,SIZE, SIZE);
|
||||
|
||||
}
|
||||
if (false) //DEBUG
|
||||
for (var i=0; i < blocks.length; i++){
|
||||
var block = blocks[i];
|
||||
ctx.drawImage(monsterImage, block.x, block.y ,SIZE, SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (player.dead){
|
||||
ctx.fillStyle = "red";
|
||||
ctx.font = "48px Helvetica";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillText("Game Over", canvas.width / 2, canvas.height/ 2);
|
||||
}
|
||||
};
|
||||
|
||||
function drawBackground(){
|
||||
for (var i= 0; i < background.length; i++){
|
||||
var b = background[i];
|
||||
|
||||
//ctx.drawImage(backgroundImage.center, b.x, b.y ,SIZE, SIZE);
|
||||
for (var j= 0; j < b.directions.length; j++){
|
||||
var d = b.directions[j];
|
||||
ctx.drawImage(backgroundImage[d], b.x, b.y ,SIZE, SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
var TO_RADIANS = Math.PI/180;
|
||||
|
||||
//http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/
|
||||
function drawRotated(image, x, y, angle) {
|
||||
var halfWidth = image.width/2;
|
||||
var halfHeight = image.height/2;
|
||||
ctx.save();
|
||||
ctx.translate(x +halfWidth, y + halfHeight);
|
||||
ctx.rotate(angle * TO_RADIANS);
|
||||
ctx.drawImage(image, -halfWidth, -halfHeight);
|
||||
ctx.restore();
|
||||
}
|
||||
21
404_games/pacman/js/game.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// The main game loop
|
||||
var main = function () {
|
||||
var now = Date.now();
|
||||
var delta = now - then;
|
||||
|
||||
update(delta / 1000);
|
||||
render();
|
||||
|
||||
then = now;
|
||||
|
||||
// Request to do this again ASAP
|
||||
requestAnimationFrame(main);
|
||||
};
|
||||
|
||||
// Cross-browser support for requestAnimationFrame
|
||||
var w = window;
|
||||
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
|
||||
|
||||
// Let's play this game!
|
||||
var then = Date.now();
|
||||
main();
|
||||
12
404_games/pacman/js/objects.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// Game objects
|
||||
var player = {
|
||||
direction: LEFT,
|
||||
speed: 100,
|
||||
sprite: 0
|
||||
}
|
||||
|
||||
var enemies = [];
|
||||
var dots = [];
|
||||
var blocks = [];
|
||||
|
||||
var background = [];
|
||||
75
404_games/pacman/js/objectsLoad.js
Normal file
@@ -0,0 +1,75 @@
|
||||
var BLACK = {r: 0, g: 0, b: 0};
|
||||
var WHITE = {r: 255, g: 255, b: 255};
|
||||
var YELLOW = {r: 255, g: 255, b: 0};
|
||||
var GREEN = {r: 0, g: 255, b: 0};
|
||||
var ORANGE = {r: 255, g: 127, b: 0};
|
||||
var CYAN = {r: 0, g: 255, b: 255};
|
||||
var RED = {r: 255, g: 0, b: 0};
|
||||
var PINK = {r: 255, g: 0, b: 255};
|
||||
|
||||
var addEnemy = function(x, y){
|
||||
var enemy = {
|
||||
direction: DOWN,
|
||||
speed: 100,
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
enemies.push(enemy);
|
||||
}
|
||||
|
||||
var bg = function(x, y , dirs) {
|
||||
return {
|
||||
x: x * SIZE,
|
||||
y: y * SIZE,
|
||||
directions: dirs
|
||||
}
|
||||
}
|
||||
|
||||
loadImagePixels("data/map.png", function(pixels){
|
||||
|
||||
pixelBackground(pixels);
|
||||
|
||||
for(i=0;i<pixels.length;i++){
|
||||
for(j=0;j<pixels[i].length;j++){
|
||||
var pixel = pixels[i][j];
|
||||
if (isColor(pixel,WHITE)) {} //White
|
||||
else if (isColor(pixel,BLACK)) blocks.push(p(i*SIZE,j*SIZE));
|
||||
else if (isColor(pixel,YELLOW)) dots.push(p(i*SIZE,j*SIZE));
|
||||
else if (isColor(pixel,GREEN)) { player.x =i*SIZE ; player.y =j*SIZE; }
|
||||
|
||||
else if (isColor(pixel,RED) || isColor(pixel,CYAN) || isColor(pixel,PINK) || isColor(pixel,ORANGE)) { addEnemy(i* SIZE, j*SIZE) }
|
||||
|
||||
else console.log("Unrecognized color in position "+i+"x"+j,pixel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var pixelBackground = function(pixels, x, y){
|
||||
var type = "undefined";
|
||||
for(i=0;i<pixels.length;i++){
|
||||
for(j=0;j<pixels[i].length;j++){
|
||||
var pixel = pixels[i][j];
|
||||
if (isColor(pixel,BLACK)) {
|
||||
|
||||
var dirs = [];
|
||||
|
||||
if (pixelIsBlock(pixels, i -1, j) ) dirs.push("left");
|
||||
if (pixelIsBlock(pixels,i +1, j)) dirs.push("right");
|
||||
if (pixelIsBlock(pixels,i, j-1)) dirs.push("up");
|
||||
if (pixelIsBlock(pixels,i, j +1)) dirs.push("down");
|
||||
|
||||
//console.log("Adding bg item " , i, j , dirs);
|
||||
background.push(bg(i,j,dirs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var pixelIsBlock = function(pixels, x, y){
|
||||
try{
|
||||
return isColor(pixels[x][y], BLACK);
|
||||
} catch (e){return false; }
|
||||
}
|
||||
|
||||
var isColor = function(rgb, color) {
|
||||
return rgb.r == color.r && rgb.g == color.g && rgb.b == color.b;
|
||||
}
|
||||
50
404_games/pacman/js/update.js
Normal file
@@ -0,0 +1,50 @@
|
||||
var playerSpriteTimeout ;
|
||||
// Update game objects
|
||||
var update = function (modifier) {
|
||||
controls(modifier);
|
||||
|
||||
if (player.dead || isCollidingBlocks(player,player.direction)){
|
||||
clearTimeout(playerSpriteTimeout);
|
||||
player.isMoving = false;
|
||||
} else {
|
||||
if (!player.isMoving) {
|
||||
player.isMoving = true;
|
||||
playerSpriteTimeout = setInterval(function(){
|
||||
player.sprite = (player.sprite +1) %2;
|
||||
}, 250);
|
||||
}
|
||||
move(player, modifier);
|
||||
}
|
||||
updateEnemies(modifier); //AI
|
||||
|
||||
//Enemy collision
|
||||
for (var i= 0; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
if (collision.collision(enemy, player, SIZE)) player.dead = true;
|
||||
}
|
||||
//Eating dots
|
||||
for (var i= 0; i < dots.length; i++){
|
||||
var dot = dots[i];
|
||||
if (collision.collision(dot, player, SIZE / 2)) dots.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
var move = function(obj, modifier){
|
||||
|
||||
obj.x = obj.x + obj.direction.x * obj.speed * modifier;
|
||||
obj.y = obj.y + obj.direction.y * obj.speed * modifier;
|
||||
|
||||
if (obj.y < 0 ) obj.y = canvas.height;
|
||||
else if (obj.y > canvas.height ) obj.y = 0 ;
|
||||
}
|
||||
|
||||
var isCollidingBlocks = function(obj, direction, offset){
|
||||
if (!offset) offset = p(0,0);
|
||||
for (var i=0; i < blocks.length; i++){
|
||||
var block = blocks[i];
|
||||
|
||||
var isColliding = collision.isCollidingDirection(block, obj, direction, offset);
|
||||
if (isColliding) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
48
404_games/pacman/js/utils.js
Normal file
@@ -0,0 +1,48 @@
|
||||
var loadJSON = function (path, success, error)
|
||||
{
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.onload = function reqListener () {
|
||||
jsonData = JSON.parse(this.responseText);
|
||||
//console.log("Loading JSON data", jsonData);
|
||||
success(jsonData);
|
||||
};;
|
||||
oReq.open("get", path, true);
|
||||
oReq.send();
|
||||
}
|
||||
|
||||
var p = function(x,y){ return {x: x, y: y}; }
|
||||
|
||||
var loadImagePixels = function(image, callback){
|
||||
|
||||
var img = new Image();
|
||||
img.src = image;
|
||||
img.onload = function() {
|
||||
console.log("Image " + image + " loaded " + img.width + "x" +img.height);
|
||||
var canvas = document.createElement('canvas');
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
img.style.display = 'none';
|
||||
var imgData = ctx.getImageData(0,0,canvas.width, canvas.height);
|
||||
|
||||
var pixels = [];
|
||||
for(i=0;i<img.width;i++){
|
||||
pixels[i] = [];
|
||||
for(j=0;j<img.height;j++){
|
||||
var pixel = ctx.getImageData(i, j, 1, 1).data;
|
||||
pixels[i][j] = {r: pixel[0], g: pixel[1], b: pixel[2], a: pixel[3]};
|
||||
//console.log("Pixel ", pixel);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.remove();
|
||||
callback(pixels);
|
||||
};
|
||||
|
||||
}
|
||||
var randomBetween = function(f, to){
|
||||
return Math.floor(Math.random() * (to + 1)) + f;
|
||||
}
|
||||
BIN
404_games/snake/data/map.png
Normal file
|
After Width: | Height: | Size: 269 B |
15
404_games/snake/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 snake</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id='canvas' height="480" width="512" border=1></canvas>
|
||||
<script src="js/logic.js"></script>
|
||||
<script src="js/controls.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/draw.js"></script>
|
||||
<script src="js/framework.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
20
404_games/snake/js/controls.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Handle keyboard controls
|
||||
var keysDown = {};
|
||||
|
||||
var KEY_UP =38, KEY_DOWN =40, KEY_LEFT =37, KEY_RIGHT =39;
|
||||
|
||||
addEventListener("keydown", function (e) {
|
||||
keysDown[e.keyCode] = true;
|
||||
}, false);
|
||||
|
||||
addEventListener("keyup", function (e) {
|
||||
delete keysDown[e.keyCode];
|
||||
}, false);
|
||||
|
||||
//Called from update.js
|
||||
var controls = function(){
|
||||
if (KEY_LEFT in keysDown) GAME_STATE.snake.move('l');
|
||||
if (KEY_RIGHT in keysDown) GAME_STATE.snake.move('r');
|
||||
if (KEY_UP in keysDown) GAME_STATE.snake.move('u');
|
||||
if (KEY_DOWN in keysDown) GAME_STATE.snake.move('d');
|
||||
}
|
||||
43
404_games/snake/js/draw.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// Create the canvas
|
||||
var canvas = document.getElementById("canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
var SIZE = 32;
|
||||
|
||||
Cell.prototype.draw = function(){
|
||||
switch(this.content){
|
||||
case 'SNAKE':
|
||||
ctx.fillStyle="gray";
|
||||
break;
|
||||
case 'BLOCK':
|
||||
ctx.fillStyle="black";
|
||||
break;
|
||||
case 'FOOD':
|
||||
ctx.fillStyle="silver";
|
||||
break;
|
||||
}
|
||||
if (this.content && this.content != 'INVALID'){
|
||||
ctx.fillRect(this.x*BLOCK_SIZE, this.y*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw everything
|
||||
var render = function () {
|
||||
if (GAME_STATE.game_over) {
|
||||
ctx.fillStyle = "rgb(250, 0, 0)";
|
||||
ctx.font = "48px Helvetica";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillText("Game Over", canvas.width / 2, canvas.height * 2 / 3);
|
||||
}
|
||||
else {
|
||||
// draw the background
|
||||
ctx.fillStyle="white";
|
||||
ctx.fillRect(0,0,canvas.width,canvas.height);
|
||||
|
||||
// draw game state
|
||||
Object.keys(GAME_STATE.grid).forEach(function(key){
|
||||
GAME_STATE.grid[key].draw();
|
||||
});
|
||||
}
|
||||
};
|
||||
34
404_games/snake/js/framework.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// The main game loop
|
||||
var main = function () {
|
||||
var now = Date.now();
|
||||
var delta = now - then;
|
||||
|
||||
controls();
|
||||
render();
|
||||
|
||||
then = now;
|
||||
|
||||
// Request to do this again ASAP
|
||||
requestAnimationFrame(main);
|
||||
};
|
||||
|
||||
//var canvas = document.createElement('canvas');
|
||||
//document.body.appendChild(canvas);
|
||||
|
||||
|
||||
|
||||
setInterval(function(){update()}, 300);
|
||||
|
||||
// Cross-browser support for requestAnimationFrame
|
||||
var w = window;
|
||||
requestAnimationFrame =
|
||||
(
|
||||
w.requestAnimationFrame ||
|
||||
w.webkitRequestAnimationFrame ||
|
||||
w.msRequestAnimationFrame ||
|
||||
w.mozRequestAnimationFrame
|
||||
);
|
||||
|
||||
// Let's play this game!
|
||||
var then = Date.now();
|
||||
initGameState(main);
|
||||
140
404_games/snake/js/logic.js
Normal file
@@ -0,0 +1,140 @@
|
||||
var BLOCK_SIZE = 16;
|
||||
|
||||
function update(){
|
||||
if (GAME_STATE.complete) GAME_STATE.snake.update();
|
||||
}
|
||||
|
||||
function initGameState(callback){
|
||||
GAME_STATE.grid = {};
|
||||
loadImagePixels("data/map.png", function(rows){
|
||||
rows.forEach(function(row, i){
|
||||
row.forEach(function(pixel, j){
|
||||
var cell = new Cell(i,j);
|
||||
if (isColor(pixel, BLACK))
|
||||
cell.content = 'BLOCK';
|
||||
else if (isColor(pixel, GREEN))
|
||||
cell.content = 'INVALID';
|
||||
else if (isColor(pixel, RED)){
|
||||
cell.content = 'SNAKE';
|
||||
GAME_STATE.snake = new Snake(cell);
|
||||
}
|
||||
GAME_STATE.grid[[i,j]] = cell;
|
||||
GAME_STATE.gameHeight = i;
|
||||
GAME_STATE.gameWidth = j;
|
||||
});
|
||||
});
|
||||
Grid.newFood();
|
||||
GAME_STATE.complete = true;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
var GAME_STATE = {
|
||||
snake: null,
|
||||
grid: null,
|
||||
gameOver: false,
|
||||
gameHeight: 0,
|
||||
gameWidth: 0,
|
||||
}
|
||||
|
||||
function Grid(){}
|
||||
|
||||
Grid.get = function(x,y){
|
||||
return GAME_STATE.grid[[x,y]];
|
||||
}
|
||||
|
||||
Grid.set = function(x, y, content){
|
||||
var cell = GAME_STATE.grid[[x,y]];
|
||||
cell.content = content;
|
||||
return cell;
|
||||
}
|
||||
|
||||
Grid.unset = function(x, y){
|
||||
var cell = GAME_STATE.grid[[x,y]];
|
||||
cell.content = null;
|
||||
return cell;
|
||||
}
|
||||
|
||||
Grid.randomFree = function(){
|
||||
do{
|
||||
var row = Math.floor(Math.random() * GAME_STATE.gameHeight);
|
||||
var col = Math.floor(Math.random() * GAME_STATE.gameWidth);
|
||||
var cell = this.get(row,col);
|
||||
} while (cell.content);
|
||||
return cell;
|
||||
}
|
||||
|
||||
Grid.newFood = function (){
|
||||
var freeCell = this.randomFree();
|
||||
freeCell.content = 'FOOD';
|
||||
}
|
||||
|
||||
function Cell(x,y){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.content = null;
|
||||
}
|
||||
|
||||
|
||||
function Snake(initCell){
|
||||
this.body = [initCell];
|
||||
this.dir = {x: -1, y: 0}; // start moving to the left
|
||||
}
|
||||
|
||||
Snake.prototype.head = function(){
|
||||
return this.body[0];
|
||||
}
|
||||
|
||||
Snake.prototype.tail = function(){
|
||||
return this.body[-1];
|
||||
}
|
||||
|
||||
Snake.prototype.move = function(dir){
|
||||
switch(dir){
|
||||
case 'l':
|
||||
this.dir = {x: -1, y: 0};
|
||||
break;
|
||||
case 'r':
|
||||
this.dir = {x: 1, y: 0};
|
||||
break;
|
||||
case 'u':
|
||||
this.dir = {x: 0, y: -1};
|
||||
break;
|
||||
case 'd':
|
||||
this.dir = {x: 0, y: 1};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Snake.prototype.update = function(dir){
|
||||
// compute new position of the head
|
||||
var head = this.head();
|
||||
var dir = this.dir;
|
||||
var newX = head.x + dir.x;
|
||||
var newY = head.y + dir.y;
|
||||
var newHead = Grid.get(newX, newY);
|
||||
|
||||
// check collisions
|
||||
|
||||
// if food, grow (on the head)
|
||||
if (newHead.content == 'FOOD') {
|
||||
newHead.content = 'SNAKE';
|
||||
this.body.unshift(newHead);
|
||||
Grid.newFood();
|
||||
}
|
||||
|
||||
// if block, die
|
||||
else if (newHead.content != null){
|
||||
GAME_STATE.game_over = true;
|
||||
}
|
||||
|
||||
// else, move
|
||||
else {
|
||||
oldTail = this.body.pop();
|
||||
oldTail.content = null;
|
||||
|
||||
newHead.content = 'SNAKE';
|
||||
this.body.unshift(newHead);
|
||||
}
|
||||
|
||||
}
|
||||
47
404_games/snake/js/utils.js
Normal file
@@ -0,0 +1,47 @@
|
||||
var loadImagePixels = function(image, callback){
|
||||
|
||||
var img = new Image();
|
||||
img.src = image;
|
||||
img.onload = function() {
|
||||
console.log("Image " + image + " loaded " + img.width + "x" +img.height);
|
||||
var canvas = document.createElement('canvas');
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
img.style.display = 'none';
|
||||
var imgData = ctx.getImageData(0,0,canvas.width, canvas.height);
|
||||
|
||||
var pixels = [];
|
||||
for(i=0;i<img.width;i++){
|
||||
pixels[i] = [];
|
||||
for(j=0;j<img.height;j++){
|
||||
var pixel = ctx.getImageData(i, j, 1, 1).data;
|
||||
pixels[i][j] = {r: pixel[0], g: pixel[1], b: pixel[2], a: pixel[3]};
|
||||
}
|
||||
}
|
||||
canvas.remove();
|
||||
callback(pixels);
|
||||
};
|
||||
}
|
||||
|
||||
var BLACK = {r: 0, g: 0, b: 0};
|
||||
var WHITE = {r: 255, g: 255, b: 255};
|
||||
var YELLOW = {r: 255, g: 255, b: 0};
|
||||
var GREEN = {r: 0, g: 255, b: 0};
|
||||
var ORANGE = {r: 255, g: 127, b: 0};
|
||||
var CYAN = {r: 0, g: 255, b: 255};
|
||||
var RED = {r: 255, g: 0, b: 0};
|
||||
var PINK = {r: 255, g: 0, b: 255};
|
||||
|
||||
var pixelIsColor = function(pixels, x, y, color){
|
||||
try{
|
||||
return isColor(pixels[x][y], color);
|
||||
} catch (e){return false; }
|
||||
}
|
||||
|
||||
var isColor = function(rgb, color) {
|
||||
return rgb.r == color.r && rgb.g == color.g && rgb.b == color.b;
|
||||
}
|
||||
24
404_games/space-invaders/enemies.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{ "four": [
|
||||
{"x": 0, "y": 0},
|
||||
{"x": 0, "y": 1},
|
||||
{"x": 1, "y": 1},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 2, "y": 3},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 2, "y": 0},
|
||||
{"x": 2, "y": 1}
|
||||
],
|
||||
"zero": [
|
||||
{"x": 0, "y": 0},
|
||||
{"x": 0, "y": 1},
|
||||
{"x": 0, "y": 2},
|
||||
{"x": 0, "y": 3},
|
||||
{"x": 1, "y": 0},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 2, "y": 3},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 2, "y": 0},
|
||||
{"x": 2, "y": 1},
|
||||
{"x": 1, "y": 3}
|
||||
]
|
||||
}
|
||||
BIN
404_games/space-invaders/images/32_enemy.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
404_games/space-invaders/images/32_laser_blue.png
Normal file
|
After Width: | Height: | Size: 597 B |
BIN
404_games/space-invaders/images/32_laser_red.png
Normal file
|
After Width: | Height: | Size: 460 B |
BIN
404_games/space-invaders/images/32_player.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
404_games/space-invaders/images/64_1.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
404_games/space-invaders/images/64_2.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
404_games/space-invaders/images/64_laser_blue.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
404_games/space-invaders/images/64_laser_red.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
404_games/space-invaders/images/background.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
20
404_games/space-invaders/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 Space Invaders</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id='canvas' height="480" width="512"></canvas>
|
||||
<script src="js/utils.js"></script>
|
||||
|
||||
<script src="js/assets.js"></script>
|
||||
<script src="js/draw.js"></script>
|
||||
<script src="js/update.js"></script>
|
||||
<script src="js/controls.js"></script>
|
||||
<script src="js/objects.js"></script>
|
||||
<script src="js/ai.js"></script>
|
||||
|
||||
<script src="js/game.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
41
404_games/space-invaders/js/ai.js
Normal file
@@ -0,0 +1,41 @@
|
||||
var updateEnemies = function(){
|
||||
|
||||
if (hasReachedEnd()) {
|
||||
changeEnemyDirection();
|
||||
return;
|
||||
}
|
||||
var enemyMovement;
|
||||
if (enemyDirection == LEFT) enemyMovement = -10;
|
||||
else enemyMovement = 10;
|
||||
|
||||
for (var i = 0 ; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
enemy.x = enemy.x + enemyMovement ;
|
||||
}
|
||||
}
|
||||
|
||||
var hasReachedEnd = function(){
|
||||
var threshold = 32;
|
||||
|
||||
for (var i = 0 ; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
if (enemyDirection == RIGHT && enemy.x > canvas.width - threshold - 32) return true;
|
||||
else if (enemyDirection == LEFT && enemy.x < threshold) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var changeEnemyDirection = function(){
|
||||
if (enemyDirection == LEFT) enemyDirection = RIGHT;
|
||||
else enemyDirection = LEFT;
|
||||
|
||||
for (var i = 0 ; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
enemy.y = enemy.y + 30 ;
|
||||
}
|
||||
}
|
||||
|
||||
var enemyShot = function(){
|
||||
var enemy = enemies[Math.floor(Math.random()*enemies.length)];
|
||||
enemyShots.push({x:enemy.x, y: enemy.y});
|
||||
}
|
||||
45
404_games/space-invaders/js/assets.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
Ship and laser assets by Cpt_Flash
|
||||
Available at: http://opengameart.org/content/space-ships-2-units
|
||||
License: GPL 3.0
|
||||
**/
|
||||
|
||||
// Background image
|
||||
var bgReady = false;
|
||||
var bgImage = new Image();
|
||||
|
||||
bgImage.onload = function () {
|
||||
bgReady = true;
|
||||
};
|
||||
bgImage.src = "images/background.png";
|
||||
|
||||
// Hero image
|
||||
var heroReady = false;
|
||||
var heroImage = new Image();
|
||||
heroImage.onload = function () {
|
||||
heroReady = true;
|
||||
};
|
||||
heroImage.src = "images/32_player.png";
|
||||
|
||||
// Monster image
|
||||
var monsterReady = false;
|
||||
var monsterImage = new Image();
|
||||
monsterImage.onload = function () {
|
||||
monsterReady = true;
|
||||
};
|
||||
monsterImage.src = "images/32_enemy.png";
|
||||
|
||||
// Hero image
|
||||
var shotReady = false;
|
||||
var shotImage = new Image();
|
||||
shotImage.onload = function () {
|
||||
shotReady = true;
|
||||
};
|
||||
shotImage.src = "images/32_laser_blue.png";
|
||||
|
||||
var shotRedReady = false;
|
||||
var shotRedImage = new Image();
|
||||
shotRedImage.onload = function () {
|
||||
shotRedReady = true;
|
||||
};
|
||||
shotRedImage.src = "images/32_laser_red.png";
|
||||
40
404_games/space-invaders/js/controls.js
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Handle keyboard controls
|
||||
var keysDown = {};
|
||||
|
||||
var KEY_UP =38, KEY_DOWN =40, KEY_LEFT =37, KEY_RIGHT =39;
|
||||
|
||||
addEventListener("keydown", function (e) {
|
||||
keysDown[e.keyCode] = true;
|
||||
}, false);
|
||||
|
||||
addEventListener("keyup", function (e) {
|
||||
delete keysDown[e.keyCode];
|
||||
}, false);
|
||||
|
||||
addEventListener("mousemove", function(evt) {
|
||||
hero.x = evt.pageX - 24 ;
|
||||
}, false);
|
||||
|
||||
var lastShot = 0;
|
||||
var SHOT_DELAY = 1000;
|
||||
|
||||
addEventListener("click", function(evt) {
|
||||
if (!hero.dead) {
|
||||
var now = new Date().getTime();
|
||||
if (lastShot +SHOT_DELAY < now ) {
|
||||
lastShot = now;
|
||||
playerShots.push({x:evt.pageX, y: hero.y});
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
|
||||
//Called from update.js
|
||||
var controls = function(modifier){
|
||||
if (KEY_LEFT in keysDown) { // Player holding left
|
||||
hero.x -= hero.speed * modifier;
|
||||
}
|
||||
if (KEY_RIGHT in keysDown) { // Player holding right
|
||||
hero.x += hero.speed * modifier;
|
||||
}
|
||||
}
|
||||
45
404_games/space-invaders/js/draw.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// Create the canvas
|
||||
var canvas = document.getElementById("canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
var SIZE = 32;
|
||||
|
||||
var vy = 0;
|
||||
// Draw everything
|
||||
var render = function () {
|
||||
if (bgReady) {
|
||||
|
||||
ctx.drawImage(bgImage, 0, vy);
|
||||
ctx.drawImage(bgImage, 0, bgImage.height-Math.abs(vy));
|
||||
|
||||
if (Math.abs(vy) > bgImage.height) vy = 0;
|
||||
vy -= 2;
|
||||
}
|
||||
|
||||
if (heroReady && !hero.dead) {
|
||||
ctx.drawImage(heroImage, hero.x, hero.y,SIZE, SIZE);
|
||||
}
|
||||
|
||||
for (var i=0; i < enemies.length; i++){
|
||||
var enemy = enemies[i];
|
||||
ctx.drawImage(monsterImage, enemy.x, enemy.y,SIZE, SIZE);
|
||||
|
||||
}
|
||||
for (var i=0; i < enemyShots.length; i++){
|
||||
var shot = enemyShots[i];
|
||||
ctx.drawImage(shotRedImage, shot.x, shot.y ,SIZE, SIZE);
|
||||
}
|
||||
|
||||
for (var i=0; i < playerShots.length; i++){
|
||||
var shot = playerShots[i];
|
||||
ctx.drawImage(shotImage, shot.x, shot.y ,SIZE, SIZE);
|
||||
}
|
||||
|
||||
if (hero.dead){
|
||||
ctx.fillStyle = "rgb(250, 0, 0)";
|
||||
ctx.font = "48px Helvetica";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillText("Game Over", canvas.width / 2, canvas.height/ 2);
|
||||
}
|
||||
};
|
||||
28
404_games/space-invaders/js/game.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// Reset the game when the player catches a monster
|
||||
var reset = function () {
|
||||
hero.x = canvas.width / 2;
|
||||
hero.y = canvas.height - 64;
|
||||
};
|
||||
|
||||
// The main game loop
|
||||
var main = function () {
|
||||
var now = Date.now();
|
||||
var delta = now - then;
|
||||
|
||||
update(delta / 1000);
|
||||
render();
|
||||
|
||||
then = now;
|
||||
|
||||
// Request to do this again ASAP
|
||||
requestAnimationFrame(main);
|
||||
};
|
||||
|
||||
// Cross-browser support for requestAnimationFrame
|
||||
var w = window;
|
||||
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
|
||||
|
||||
// Let's play this game!
|
||||
var then = Date.now();
|
||||
reset();
|
||||
main();
|
||||
29
404_games/space-invaders/js/objects.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// Game objects
|
||||
var hero = {};
|
||||
var playerShots = [];
|
||||
var enemyShots = [];
|
||||
|
||||
var shotSpeed = 200;
|
||||
|
||||
var RIGHT = 1, LEFT = 0;
|
||||
var enemies = [];
|
||||
var enemyDirection = RIGHT;
|
||||
var loadEnemy = function(offset, json){
|
||||
var size = 32;
|
||||
|
||||
for (var i = 0; i< json.length; i++){
|
||||
var pos = json[i];
|
||||
var enemy = {x: offset.x + pos.x * size, y: offset.y + pos.y * size} ;
|
||||
enemies.push(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
loadJSON('enemies.json',
|
||||
function(data) {
|
||||
|
||||
loadEnemy({ x: 50, y: 50 }, data.four);
|
||||
loadEnemy({ x: 180, y: 50 }, data.zero);
|
||||
loadEnemy({ x: 300, y: 50 }, data.four);
|
||||
},
|
||||
function(xhr) { console.error(xhr); }
|
||||
);
|
||||
45
404_games/space-invaders/js/update.js
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
// Update game objects
|
||||
var update = function (modifier) {
|
||||
controls(modifier);
|
||||
|
||||
for (var i = 0; i< playerShots.length; i++){
|
||||
var shot = playerShots[i];
|
||||
shot.y = shot.y - modifier * shotSpeed;
|
||||
|
||||
for (var e= 0; e < enemies.length; e++){
|
||||
var enemy = enemies[e];
|
||||
if (collision(shot, enemy)) {
|
||||
console.log("Collision with enemy ", shot, enemy);
|
||||
playerShots.splice(i, 1);
|
||||
enemies.splice(e, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i< enemyShots.length; i++){
|
||||
var shot = enemyShots[i];
|
||||
shot.y = shot.y + modifier * shotSpeed;
|
||||
|
||||
if (collision(shot, hero)) {
|
||||
console.log("Collision with hero ", shot, hero);
|
||||
enemyShots.splice(i, 1);
|
||||
hero.dead = true;
|
||||
}
|
||||
}
|
||||
//updateEnemies();
|
||||
// Are they touching?
|
||||
};
|
||||
|
||||
var collision = function(shot, enemy){
|
||||
return shot.x <= (enemy.x + 32)
|
||||
&& enemy.x <= (shot.x + 32)
|
||||
&& shot.y <= (enemy.y + 32)
|
||||
&& enemy.y <= (shot.y + 32)
|
||||
}
|
||||
|
||||
//AI METHODS
|
||||
setInterval(function(){updateEnemies()}, 500);
|
||||
|
||||
setInterval(function(){enemyShot()}, 1000);
|
||||
11
404_games/space-invaders/js/utils.js
Normal file
@@ -0,0 +1,11 @@
|
||||
var loadJSON = function (path, success, error)
|
||||
{
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.onload = function reqListener () {
|
||||
jsonData = JSON.parse(this.responseText);
|
||||
console.log("Loading JSON data", jsonData);
|
||||
success(jsonData);
|
||||
};;
|
||||
oReq.open("get", path, true);
|
||||
oReq.send();
|
||||
}
|
||||
8
Docker-404-games.iml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="GENERAL_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM python:slim
|
||||
|
||||
LABEL authors="tebarius"
|
||||
LABEL version="1.2.1"
|
||||
LABEL description="QR-Code-Generator-Server with Flask-App"
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./app /app/
|
||||
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install --trusted-host pypi.python.org -r requirements.txt
|
||||
|
||||
EXPOSE 8002
|
||||
|
||||
ENV HTTP_METHOD POST
|
||||
|
||||
CMD ["sh", "-c", "python ${HTTP_METHOD}-Flask-QR.py"]
|
||||
49
readme.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Flask QR-Code-Generator
|
||||
Sorry folks, because this project startet as experiment for Flask and Docker only german description and manual.
|
||||
|
||||
HTTP-Server auf Port 8002 mit QR-Code-Generator zur Generierung verschiedener Arten von QR-Codes (Text, URL, Mail, Tel., WIFI, Kalender-Event, vCard, MeCard).
|
||||
|
||||
Eigentlich ist das Projekt für mich ein Experimentierfeld gewesen um mal Flask ein bisschen auszuprobieren
|
||||
|
||||
## ohne Docker
|
||||
Um lokal das ganze zu testen werden nur die Dateien aus dem app-Verzeichnis benötigt.
|
||||
Voraussetzung ist eine funktionierende Python Installation (ich habe nur mit Python 3.11 und 3.12 getestet) und das Flask-Framework inclusive Flask-QRcode welches sich recht einfach über die Konsole mit ...
|
||||
|
||||
pip install Flask-QRcode
|
||||
... installieren lässt.
|
||||
|
||||
Zum Starten dann eine der beiden .py Dateien benutzen, je nachdem welcher
|
||||
HTTP-Modus gewollt ist. Im Zweifelsfall POST ... nehmen und wenn ein Doppelklick nicht geht dann halt über die Konsole: `python POST-Flask-QR.py`
|
||||
|
||||
Der Server ist dann via http://localhost:8002 zu erreichen
|
||||
|
||||
## Docker
|
||||
Es gibt 2 unterschiedliche Dockerfile's, da obwohl bei beiden python:slim als Basis genutzt wird,
|
||||
noch die Installation von ein paar packages zusätzlich notwendig ist, damit flask auch auf
|
||||
dem RaspberryPi 3 via pip install integriert werden kann.
|
||||
|
||||
In der Standardeinstellung werden die Formulare mit HTTP-POST-Anfragen gesendet/verarbeitet.
|
||||
Sollte es Gründe geben, warum gewünscht wird, dass dies der HTTP-GET-Variante zu machen, lässt sich das über die Enviroment Variable HTTP_METHOD ändern.
|
||||
|
||||
## Enviroment-Variablen
|
||||
|
||||
- `HTTP_METHOD` GET oder POST (default: POST)
|
||||
|
||||
## Docker Installation/Start
|
||||
https://hub.docker.com/r/tebarius/flask-qrcode-generator
|
||||
### Linux/AMD64
|
||||
- einfacher Start:
|
||||
`docker run -d -p 8002:8002 ghcr.io/tebarius/flask-qrcode-generator:latest`
|
||||
erreichbar dann z.B. via http://localhost:8002
|
||||
- mit HTTP-Methode GET auf Port 80:
|
||||
`docker run -d -p 80:8002 -e HTTP_METHOD=GET ghcr.io/tebarius/flask-qrcode-generator:latest`
|
||||
erreichbar dann z.B. via http://localhost
|
||||
|
||||
### Linux/ARMv7 (getestet mit RaspberryPi 3)
|
||||
- einfacher Start:
|
||||
`docker run -d -p 8002:8002 ghcr.io/tebarius/flask-qrcode-generator:armv7-latest`
|
||||
erreichbar dann z.B. via http://localhost:8002
|
||||
- mit HTTP-Methode GET auf Port80:
|
||||
`docker run -d -p 80:8002 -e HTTP_METHOD=GET ghcr.io/tebarius/flask-qrcode-generator:armv7-latest`
|
||||
erreichbar dann z.B. via http://localhost
|
||||
|
||||