From 04808a00768c559fdc0f177d6dd1fde37c49bbeb Mon Sep 17 00:00:00 2001 From: monsterkodi Date: Mon, 8 Aug 2016 21:00:20 +0200 Subject: [PATCH] world --- coffee/levels/move.coffee | 2 +- coffee/main.coffee | 121 +++++++++++++ coffee/world.coffee | 362 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 coffee/main.coffee create mode 100644 coffee/world.coffee diff --git a/coffee/levels/move.coffee b/coffee/levels/move.coffee index c97e486..7ca6599 100644 --- a/coffee/levels/move.coffee +++ b/coffee/levels/move.coffee @@ -21,7 +21,7 @@ module.exports = position: [0,0,0] ] create: -> -# + s = world.getSize() world.addObjectAtPos(KikiStone(), KikiPos(s.x/2-1, s.y/2+1, 0)) diff --git a/coffee/main.coffee b/coffee/main.coffee new file mode 100644 index 0000000..4eefe83 --- /dev/null +++ b/coffee/main.coffee @@ -0,0 +1,121 @@ + +# 000 000 000 000 000 000 +# 000 000 000 000 000 000 +# 0000000 000 0000000 000 +# 000 000 000 000 000 000 +# 000 000 000 000 000 000 + +Stage = require '/Users/kodi/s/ko/js/area/stage' +log = require '/Users/kodi/s/ko/js/tools/log' + +KikiWorld = require './world' + +class Kiki extends Stage + + constructor: (@view) -> super @view + + start: -> + + world = new KikiWorld() + log 'hello world' + + @elem = document.createElement 'div' + @elem.style.position = 'absolute' + @elem.style.top = '0' + @elem.style.left = '0' + @elem.style.right = '0' + @elem.style.bottom = '0' + @elem.style.background = "#004" + @view.appendChild @elem + + @renderer = new THREE.WebGLRenderer + antialias: true + logarithmicDepthBuffer: true + autoClear: true + + @renderer.setClearColor 0x008800 + @elem.appendChild @renderer.domElement + @renderer.setSize @view.offsetWidth, @view.offsetHeight + + + # 0000000 0000000 00 00 00000000 00000000 0000000 + # 000 000 000 000 000 000 000 000 000 000 + # 000 000000000 000000000 0000000 0000000 000000000 + # 000 000 000 000 0 000 000 000 000 000 000 + # 0000000 000 000 000 000 00000000 000 000 000 000 + + @fov = 60 + @near = 10 + @far = 1000 + @aspect = @view.offsetWidth / @view.offsetHeight + @dist = 20 + + @camera = new THREE.PerspectiveCamera @fov, @aspect, @near, @far + @camera.position.z = @dist + + # 0000000 0000000 00000000 000 000 00000000 + # 000 000 000 0000 000 000 + # 0000000 000 0000000 000 0 000 0000000 + # 000 000 000 000 0000 000 + # 0000000 0000000 00000000 000 000 00000000 + + @scene = new THREE.Scene() + @geom = new THREE.BoxGeometry 10, 10, 10 + + # 000 000 0000000 000 000 000000000 + # 000 000 000 000 000 000 + # 000 000 000 0000 000000000 000 + # 000 000 000 000 000 000 000 + # 0000000 000 0000000 000 000 000 + + @sun = new THREE.PointLight 0xffff00 + @sun.position.copy @camera.position + @scene.add @sun + + @ambient = new THREE.AmbientLight 0x444444 + @scene.add @ambient + + # @material = new THREE.MeshPhongMaterial + # color: 0xff0000 + # side: THREE.FrontSide + # shading: THREE.SmoothShading + # transparent: true + # opacity: 0.85 + # shininess: 0 +# + # @mesh = new THREE.Mesh @geom, @material + # @scene.add @mesh + + @animate() + + # 0000000 000000000 00000000 00000000 + # 000 000 000 000 000 + # 0000000 000 0000000 00000000 + # 000 000 000 000 + # 0000000 000 00000000 000 + + animationStep: (step) => + + @quat = @camera.quaternion.clone() + @quat.multiply (new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(1,0,0), step.dsecs*0.2) + @quat.multiply (new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(0,1,0), step.dsecs*0.1) + @camera.position.set(0,0,@dist).applyQuaternion @quat + @camera.quaternion.copy @quat + @sun.position.copy @camera.position + @renderer.render @scene, @camera + + reset: -> + @elem.style.display = 'block' + @resume() + + stop: -> + @elem.style.display = 'none' + @pause() + + resized: (w,h) -> + @aspect = w/h + @camera?.aspect = @aspect + @camera.updateProjectionMatrix() + @renderer?.setSize w,h + +module.exports = Kiki diff --git a/coffee/world.coffee b/coffee/world.coffee new file mode 100644 index 0000000..cdac490 --- /dev/null +++ b/coffee/world.coffee @@ -0,0 +1,362 @@ + +log = require "/Users/kodi/s/ko/js/tools/log" +KQuaternion = require './lib/quaternion' +KVector = require './lib/vector' + +class KikiWorld + + constructor: -> + + # execfile(kikipy_path + "colors.py") + # execfile(kikipy_path + "action.py") + # execfile(kikipy_path + "lang.py") + # execfile (kikipy_path + "config.py") + # execfile (kikipy_path + "setup.py") + # execfile (kikipy_path + "levelselection.py") + # execfile (kikipy_path + "highscore.py") + # execfile (kikipy_path + "intro.py") + + globals().rot0 = KQuaternion() + globals().rotz180 = KQuaternion.rotationAroundVector(180, KVector(0,0,1)) + globals().rotz90 = KQuaternion.rotationAroundVector(90, KVector(0,0,1)) + globals().roty270 = KQuaternion.rotationAroundVector(270, KVector(0,1,0)) + globals().roty180 = KQuaternion.rotationAroundVector(180, KVector(0,1,0)) + globals().roty90 = KQuaternion.rotationAroundVector(90, KVector(0,1,0)) + globals().roty0 = KQuaternion.rotationAroundVector(0, KVector(0,1,0)) + globals().rotx180 = KQuaternion.rotationAroundVector(180, KVector(1,0,0)) + globals().rotx90 = KQuaternion.rotationAroundVector(90, KVector(1,0,0)) + + @levelList = [ + "start", "steps", "move", "electro", "elevate", "throw", # intro + "gold", "jump", "escape", "gears", "gamma", "cube", "switch", "borg", # easy + "mini", "blocks", "bombs", "sandbox", "energy", "maze", "love", + "towers", "edge", "random", "plate", "nice", "entropy", # medium + "grasp", "fallen", "cheese", "invisimaze", "spiral", # owen hay's levels (TODO: sort in) + "slick", "bridge", "flower", "stones", "walls", "grid", # difficult + "rings", "core", "bronze", "pool", # difficult + "hidden", "church", "strange", "mesh", "columns", "machine", # tough + "neutron", "captured", "circuit", "regal", "conductor", "evil", # very hard + "mutants", # outro + ] + + @levelDict = {} + + # import the levels + for levelName in @levelList + @levelDict[levelName] = require "./levels/#{levelName}" + + log 'levelDict', @levelDict + @preview = false + + # 0000000 00000000 00000000 0000000 000000000 00000000 + # 000 000 000 000 000 000 000 000 + # 000 0000000 0000000 000000000 000 0000000 + # 000 000 000 000 000 000 000 000 + # 0000000 000 000 00000000 000 000 000 00000000 + + create: (worldDict={}) -> # creates the world from a level name or a dictionary + + log "world.create", worldDict + + if worldDict + if _.isString worldDict + world.level_index = levelList.index worldDict + world.level_name = worldDict + @dict = levelDict[worldDict] + else + @dict = worldDict + + # ............................................................ appearance + + world.setSize @dict["size"] + + if "scheme" in @dict + applyColorScheme eval(@dict["scheme"]) + else + applyColorScheme default_scheme + + if "border" in @dict + border = @dict["border"] + else + border = 1 + + world.setDisplayBorder border + + # ............................................................ intro text + if "intro" in @dict + if not @preview + intro_text = KikiScreenText() + intro_text.addText @dict["intro"] + intro_text.show() + world.setName @dict["intro"] + else + world.setName "noname" + + if @preview + world.getProjection().setViewport(0.0, 0.4, 1.0, 0.6) + else + world.getProjection().setViewport(0.0, 0.0, 1.0, 1.0) + + # ............................................................ escape + escape_event = Controller.getEventWithName ("escape") + escape_event.removeAllActions() + escape_event.addAction(continuous(@escape, "escape")) + + # ............................................................ exits + + if "exits" in @dict + exit_id = 0 + for entry in @dict["exits"] + exit_gate = KikiGate (entry["active"]) + + if "name" in entry + name = entry["name"] + else + name = "exit "+str(exit_id) + exit_gate.setName(name) + + exit_action = once ("exit " + str(exit_id)) + delay_action = once (lambda a = exit_action: Controller.timer_event.addAction (a)) + exit_gate.getEventWithName ("enter").addAction (delay_action) + if "position" in entry + pos = world.decenter (entry["position"]) + else if "coordinates" in entry + pos = KikiPos entry["coordinates"] + world.addObjectAtPos exit_gate, pos + exit_id += 1 + + # ............................................................ creation + + if "create" in @dict + if _.isFunction @dict["create"] + @dict["create"]() + else + exec @dict["create"] in globals() + + # ............................................................ player + + player = Controller.player + + player_dict = @dict["player"] + + if "orientation" in player_dict + player.setOrientation (player_dict["orientation"]) + else + player.setOrientation (roty90) + + if "position" in player_dict + world.addObjectAtPos player, world.decenter(player_dict["position"]) + else if "coordinates" in player_dict + pos = player_dict["coordinates"] + world.addObjectAtPos player, KikiPos(pos[0], pos[1], pos[2]) + + if "nostatus" in player_dict + if player_dict["nostatus"] or @preview + Controller.player_status.hide() + else + Controller.player_status.show() + else + if @preview + Controller.player_status.hide() + else + Controller.player_status.show() + + world.getProjection().setPosition (KVector()) + + Controller.player.getStatus().setMinMoves (highscore.levelParMoves (world.level_name)) + Controller.player.getStatus().setMoves (0) + + # ............................................................ init + world.init() # tell the world that we are finished + + restart: (self) -> + # restores the player status and restarts the current level + Controller.player.getStatus().setMoves (0) + Controller.player.reborn() + @create() + + finish: (self) -> + # saves the current level status in highscore file + highscore.levelFinished world.level_name, Controller.player.getStatus().getMoves() + + resetPlayer: (self) -> + # reset the player to it's original position and orientation + + player_dict = @dict["player"] + player = Controller.getPlayer() + + if "reset orientation" in player_dict + player.setOrientation player_dict["reset orientation"] + else if "orientation" in player_dict + player.setOrientation player_dict["orientation"] + else + player.setOrientation rot0 + + if "reset position" in player_dict + world.moveObjectToPos player, world.decenter(player_dict["reset position"]) + else + world.moveObjectToPos player, world.decenter(player_dict["position"]) + + performAction: (name, time) -> + # action callback. used to exit current world + if name.find ("exit") == 0 + @finish() + Controller.player.getStatus().setMoves (0) + if "world" in @dict["exits"][parseInt name.slice 5] + w = @dict["exits"][parseInt name.slice 5]["world"] + if w instanceof KikiWorld + w.create() + else if _.isFunction w + w() + else + exec "KikiWorld().create(" + world + ")" + else + KikiPyWorld().create (levelList[world.level_index+1]) + + activate: (objectName) -> + # activates object with name objectName + object = @getObjectWithName(objectName) + if object.getClassName() == "KikiSwitch" + kikiObjectToSwitch(object).setActive(1) + else if object.getClassName() == "KikiGate" + kikiObjectToGate(object).setActive(1) + + decenter: () -> + s = @getSize() + if len(args) == 3 + [x, y, z] = args + else if len(args) == 1 + [x, y, z] = args[0] + + return KikiPos(x+s.x/2, y+s.y/2, z+s.z/2) + + addObjectLine: (object, start, end) -> + # adds a line of objects of type to the world. start and end should be 3-tuples or KikiPos objects + if start instanceof KikiPos + start = [start.x, start.y, start.z] + [sx, sy, sz] = start + if end isinstance KikiPos + end = [end.x, end.y, end.z] + [ex, ey, ez] = end + + diff = [ex-sx, ey-sy, ez-sz] + maxdiff = _.max diff.map Math.abs + deltas = diff.map (a) -> a/maxdiff + for i in [0...maxdiff] + # pos = apply(KikiPos, (map (lambda a, b: int(a+i*b), start, deltas))) + pos = KikiPos (start[j]+i*deltas[j] for j in [0..2]) + if @isUnoccupiedPos pos + if type(object) == types.StringType + @addObjectAtPos eval(object), pos + else + @addObjectAtPos object(), pos + + addObjectPoly: (object, points, close=1) -> + # adds a polygon of objects of type to the world. points should be 3-tuples or KikiPos objects + if close + points.append (points[0]) + for index in range(1, len(points)) + @addObjectLine object, points[index-1], points[index] + + addObjectRandom: (object, number) -> + # adds number objects of type at random positions to the world + for i in [0...number] + if type (object) == types.StringType + @setObjectRandom (eval(object)) + else + @setObjectRandom (object()) + + setObjectRandom: (object) -> + # adds number objects of type at random positions to the world + size = @getSize() + object_set = 0 + while not object_set # hack alert! + random_pos = KikiPos random.randrange(size.x), + random.randrange(size.y), + random.randrange(size.z) + if not object.isSpaceEgoistic() or @isUnoccupiedPos(random_pos) + @addObjectAtPos object, random_pos + object_set = 1 + + help: (index=0) -> + # displays help messages + + # text_list = @dict["help"] + # more_text = index < len (text_list) - 1 + # less_text = index > 0 +# + # list = text_list[index].split("$key(") + # for i in range (1, len(list)) + # close = list[i].find(")") + # list[i] = Controller.player.getKeyForAction (list[i][:close]) + list[i][close+1:] +# + # list.append ("\n\n$scale(0.5)(%d/%d)" % (index+1, len (text_list))) + # help_text = KikiPageText ("".join(list), more_text, less_text) +# + # if more_text: + # help_text.getEventWithName ("next").addAction (once (lambda i=index+1: @help (i))) + # if less_text: + # help_text.getEventWithName ("previous").addAction (once (lambda i=index-1: @help (i))) + + outro: (index=0) -> + # well hidden outro :-) + outro_text = """ + $scale(1.5)congratulations!\n\n$scale(1)you rescued\nthe nano world! + + the last dumb mutant bot\nhas been destroyed.\n\nthe maker is functioning again. + kiki will go now\nand see all his new friends.\n\nyou should maybe\ndo the same? + the maker wants to thank you!\n\n(btw.: you thought\nyou didn't see\nkiki's maker in the game? + you are wrong!\nyou saw him\nall the time,\nbecause kiki\nlives inside him!)\n\n$scale(1.5)the end + p.s.: the maker of the game\nwants to thank you as well!\n\ni definitely want your feedback: + please send me a mail (monsterkodi@users.sf.net)\nwith your experiences, + which levels you liked, etc.\n\nthanks in advance and have a nice day,\n\nyours kodi + """ + + more_text = index < outro_text.length-1 + less_text = index > 0 + + page_text = outro_text[index] + page_text += "\n\n$scale(0.5)(#{index+1}/#{outro_text.length})" + + page = KikiPageText(page_text, more_text, less_text) + page.getEventWithName("hide").addAction(once(display_main_menu)) + + if more_text + page.getEventWithName("next").addAction (i=index+1) => @outro i + if less_text + page.getEventWithName("previous").addAction (i=index-1) => @outro i + + resetProjection: -> world.getProjection().setViewport 0.0, 0.0, 1.0, 1.0 + + toggle: (objectName) -> + # toggles object with name objectName + Controller.startTimedAction(@getObjectWithName(objectName).getActionWithName("toggle")) + + escape: (self) -> # handles an ESC key event + + @resetProjection() + + if "escape" in @dict + if _.isFunction @dict["escape"] + @dict["escape"]() + else + exec @dict["escape"] in globals() + return + + menu = KikiMenu() + menu.getEventWithName ("hide").addAction (once(@resetProjection)) + + # if Controller.isDebugVersion() + # menu.addItem (Controller.getLocalizedString("next level"), once(lambda w=self: w.performAction("exit 0",0))) + # if "help" in @dict + # menu.addItem (Controller.getLocalizedString("help"), once(@help)) + menu.addItem(Controller.getLocalizedString("restart"), once(@restart)) + + esc_menu_action = once (@escape) + console.out("level_index %d" % world.level_index) + menu.addItem(Controller.getLocalizedString("load level"), (i=world.level_index,a=esc_menu_action) -> levelSelection(i, a)) + menu.addItem(Controller.getLocalizedString("setup"), once(quickSetup)) + menu.addItem(Controller.getLocalizedString("about"), once(display_about)) + menu.addItem(Controller.getLocalizedString("quit"), once(Controller.quit)) + +module.exports = KikiWorld