tinks: delete the old 2D mnit client
authorAlexis Laferrière <alexis.laf@xymus.net>
Fri, 12 Jan 2018 02:47:53 +0000 (21:47 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Thu, 25 Jan 2018 14:01:17 +0000 (09:01 -0500)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

contrib/tinks/.gitignore
contrib/tinks/Makefile
contrib/tinks/README.md
contrib/tinks/doc/tinks.png [deleted file]
contrib/tinks/src/client/android_client.nit [deleted file]
contrib/tinks/src/client/assets.nit [deleted file]
contrib/tinks/src/client/client.nit [deleted file]
contrib/tinks/src/client/controls.nit [deleted file]
contrib/tinks/src/client/linux_client.nit [deleted file]

index 467c3d3..337d1e3 100644 (file)
@@ -1,3 +1,2 @@
 src/*/*_serialize.nit
-src/client/drawing.nit
 config.json
index 43536cc..ab9f82f 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-all: bin/server bin/tinks bin/tinks3d
+all: bin/server bin/tinks3d
 
-pre-build: assets/images/drawing.png src/server/server_serialize.nit
+pre-build: src/server/server_serialize.nit
 
 # Client
-bin/tinks: assets/images/drawing.png src/client/client.nit $(shell nitls -M src/client/linux_client.nit)
-       nitserial -o src/client/client_serialize.nit src/client/client.nit
-       nitc -o bin/tinks src/client/linux_client.nit -m src/client/client_serialize.nit
-
 bin/tinks3d: $(shell nitls -M src/client/client3d.nit -m linux)
        nitserial -o src/client/client_serialize.nit src/client/client3d.nit
        nitc -o bin/tinks3d src/client/client3d.nit \
                -m src/client/client_serialize.nit -m linux
 
-assets/images/drawing.png: art/drawing.svg
-       ../inkscape_tools/bin/svg_to_png_and_nit art/drawing.svg -a assets/ -s src/client/ -x 2.0
-
 # Server
 bin/server: src/server/server_serialize.nit $(shell nitls -M src/server/dedicated.nit)
        nitc -o bin/server src/server/dedicated.nit -m src/server/server_serialize.nit
@@ -37,14 +30,5 @@ src/server/server_serialize.nit: $(shell nitls -M src/server/dedicated.nit)
        nitserial -o src/server/server_serialize.nit src/server/dedicated.nit
 
 # Android
-android: bin/tinks.apk
-bin/tinks.apk: assets/images/drawing.png android/res/ $(shell nitls -M src/client/android_client.nit)
-       nitserial -o src/client/client_serialize.nit src/client/client.nit
-       nitc -o bin/tinks.apk src/client/android_client.nit -m src/client/client_serialize.nit
-
-android-release: assets/images/drawing.png android/res/ $(shell nitls -M src/client/android_client.nit)
-       nitserial -o src/client/client_serialize.nit src/client/client.nit
-       nitc -o bin/tinks.apk src/client/android_client.nit -m src/client/client_serialize.nit --release
-
 android/res/: art/icon.svg
        ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out android/res/
index ef1d143..99e2ac1 100644 (file)
@@ -30,16 +30,10 @@ It should be easy to add features as refinements on both the client and the serv
 
 # Clients and server
 
-Tinks! has two distinct clients and one dedicated server.
+Tinks! has a client and a dedicated server.
 The whole project is modular, these software share mostly the same code.
 
-* The original 2D client at `bin/tinks` uses mnit and OpenGL ES 1.0 to display the world from above.
-
-  The Android variant at `bin/tinks.apk` uses the same view from above, with added on-screen controls.
-
-  ![Screenshot of the 2D client](doc/tinks.png)
-
-* The 3D client at `bin/tinks3d` uses gamnit and OpenGL ES 2.0 for an immersive world.
+* The 3D client at `bin/tinks3d` uses `gamnit` and OpenGL ES 2.0 for an immersive world.
 
   Despite the different graphics, both client are fully compatible for multiplayer.
 
diff --git a/contrib/tinks/doc/tinks.png b/contrib/tinks/doc/tinks.png
deleted file mode 100644 (file)
index 96ffd95..0000000
Binary files a/contrib/tinks/doc/tinks.png and /dev/null differ
diff --git a/contrib/tinks/src/client/android_client.nit b/contrib/tinks/src/client/android_client.nit
deleted file mode 100644 (file)
index 376d5a6..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Android client with a joystick
-module android_client is
-       app_name "Tinks!"
-       app_namespace "net.xymus.tinks"
-       android_manifest """<uses-permission android:name="android.permission.INTERNET" />"""
-       android_api_target 10
-end
-
-import mnit::android
-import android::audio
-import android::vibration
-import android::landscape
-
-intrude import client
-import controls
-
-redef class App
-
-       # Tank direction control
-       var joystick = new Joystick is lazy
-
-       redef var controls = new Array[Control].with_items(joystick) is lazy
-
-       redef fun input(event)
-       do
-               var local_player = context.local_player
-               var local_tank = local_tank
-               if local_player != null and local_tank != null and event isa ControlEvent then
-                       local_player.orders.add new TankDirectionOrder(local_tank, joystick.value_x, joystick.value_y)
-                       return true
-               end
-
-               if event isa AndroidKeyEvent then
-                       if event.is_back_key then
-                               quit = true
-                               native_activity.finish
-                               return false
-                       end
-               end
-
-               return super
-       end
-end
-
-redef class ExplosionEvent
-       redef fun client_react(display, turn)
-       do
-               super
-
-               var local_tank = app.local_tank
-               var d = 20
-               if local_tank != null then
-                       d = local_tank.pos.dist(pos).to_i
-                       d = 100 - d*5
-                       d = d.max(10)
-               end
-
-               app.vibrator.vibrate d
-       end
-end
-
-# On-demand joystick that popups up when tapping the left border of the screen
-class Joystick
-       super Control
-
-       # Current position of the joystick from its center on the X axis, in `[-1.0..1.0]`
-       var value_x = 0.0
-
-       # Current position of the joystick from its center on the Y axis, in `[-1.0..1.0]`
-       var value_y = 0.0
-
-       # Deadzone at the center of the joystick where the values are set at 0.0
-       var deadzone = 0.3
-
-       # Position of the center of the joystick, set at where the screen is first tapped
-       var center: nullable ScreenPos
-
-       # Position of the top of the joystick, the one that follows the finger
-       var handle: nullable ScreenPos
-
-       # Id of the pointer/finger that triggered the joystick
-       var captured_pointer: Int = -1
-
-       # Image of the left border
-       var img_zone: Image = app.assets.drawing.joystick_zone
-
-       # Image of the joystick base
-       var img_back: Image = app.assets.drawing.joystick_back
-
-       # Image of the top of the joystick
-       var img_handle: Image = app.assets.drawing.joystick_handle
-
-       # Radius where the top of the joystick can move around the center
-       var radius: Float = img_back.width.to_f / 2.0 - 4.0
-
-       # Width of the left border used to trigger the joystick
-       var capture_width = 400.0
-
-       redef fun draw(display)
-       do
-               display.blit_stretched(img_zone,
-                       0, -128,
-                       0, display.height+128,
-                       capture_width, display.height+128,
-                       capture_width, -128)
-
-               var center = center
-               var handle = handle
-               if center != null and handle != null then
-                       img_back.scale = 1.0
-                       img_handle.scale = 1.0
-                       display.blit_centered(img_back, center.x, center.y)
-                       display.blit_centered(img_handle, handle.x, handle.y)
-               end
-       end
-
-       redef fun input(event)
-       do
-               if event isa AndroidPointerEvent then
-                       var center = center
-                       if center == null then
-                               # New joystick?
-                               print "New joystick? {event.just_went_down} {event.x} < {capture_width}"
-                               if event.just_went_down and
-                                  event.x < capture_width then
-                                       # Capture it!
-                                       self.center = new ScreenPos(event.x, event.y)
-                                       self.captured_pointer = event.pointer_id
-                                       self.handle = center
-                                       return true
-                               end
-                       else
-                               # Already down
-
-                               # Is it the finger already on the joystick?
-                               if captured_pointer != event.pointer_id then return false
-
-                               if event.depressed then
-                                       self.center = null
-                                       self.handle = null
-                                       self.value_x = 0.0
-                                       self.value_y = 0.0
-                               else
-                                       # Update values
-                                       var dx = center.x - event.x
-                                       var dy = center.y - event.y # This is inverted, as is the input
-                                       var d = dx.hypot_with(dy)
-                                       if d < deadzone then
-                                               self.value_x = 0.0
-                                               self.value_y = 0.0
-                                               self.handle = center
-                                       else
-                                               var a = atan2(dx, dy)+pi/2.0
-                                               self.value_x = a.cos
-                                               self.value_y = a.sin
-
-                                               if d > radius then d = radius
-                                               self.handle = new ScreenPos(center.x+a.cos*d, center.y-a.sin*d)
-                                       end
-                               end
-
-                               app.input new ControlEvent(self)
-                               return true
-                       end
-               end
-
-               return false
-       end
-end
diff --git a/contrib/tinks/src/client/assets.nit b/contrib/tinks/src/client/assets.nit
deleted file mode 100644 (file)
index 1b4b25d..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Client `Assets` and client-only services on game elements
-module assets is no_warning("attr-in-refinement")
-
-import app::audio
-
-import game
-
-import drawing
-
-redef class App
-       redef fun load_image(path)
-       do
-               var img = super
-               img.scale = 0.5
-               return img
-       end
-end
-
-redef class FeatureRule
-       # Images of different alternatives
-       var images: Array[Image]
-end
-
-redef class TankRule
-       # Image of the base tank structure, at different health level
-       var base_images: Array[Image]
-
-       # Image of the turret
-       var turret_image: Image
-end
-
-redef class Feature
-       # Rotation angle of this feature
-       var angle: Float = pi.rand
-
-       # Index within `rule.images` of the image of this instance
-       var image_index: Int = rule.images.length.rand is lazy
-end
-
-# Collection of assets
-class Assets
-
-       # Images from the `art/drawing.svg` file
-       var drawing = new DrawingImages
-       init do drawing.load_all(app)
-
-       # Firing sound
-       var turret_fire = new Sound("sounds/turret_fire.wav")
-
-       # Turret is ready to fire sound
-       var turret_ready = new Sound("sounds/turret_ready.mp3")
-
-       # Associate images to the `story` rules
-       fun assign_images_to_story(story: Story)
-       do
-               story.tree.images = drawing.trees
-               story.rock.images = drawing.rock
-               story.debris.images = drawing.debris
-
-               for tank in story.tanks do
-                       tank.base_images = drawing.tank_hit
-                       tank.turret_image = drawing.turret
-               end
-
-               story.health.images = [drawing.health]
-       end
-end
diff --git a/contrib/tinks/src/client/client.nit b/contrib/tinks/src/client/client.nit
deleted file mode 100644 (file)
index bc434b7..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Portable client
-module client
-
-import mnit
-import mnit::opengles1
-import performance_analysis
-
-import game
-import common
-
-import assets
-import base
-
-# A position within the screen
-class ScreenPos
-       super Point[Float]
-
-       # Convert to a game logic `Pos` by applying camera transformation
-       fun to_logic(camera: Camera): Pos do
-               return new Pos(x/camera.basic_zoom + camera.dx, y/camera.basic_zoom + camera.dy)
-       end
-end
-
-redef class Pos
-       # Convert to a `ScreenPos` by applying camera transformation
-       fun to_screen(camera: Camera): ScreenPos do
-               return new ScreenPos((x - camera.dx) * camera.basic_zoom, (y - camera.dy) * camera.basic_zoom)
-       end
-end
-
-# Camera managing the screen view on the world
-class Camera
-       # Offset of the top left corner of the screen, X part
-       var dx = 0.0
-
-       # Offset of the top left corner of the screen, Y part
-       var dy = 0.0
-
-       # Basic zoom, the distance between 2 features
-       #
-       # In the world logic, the distance is of 1.
-       # This value depends on the size of the graphical assets.
-       #
-       # TODO make it a full zoom by scaling images too, if needed.
-       var basic_zoom = 32.0
-
-       # Center of the `display` as world `Pos`
-       fun center(display: Display): Pos
-       do
-               return (new ScreenPos(display.width.to_f * 0.5, display.height.to_f * 0.5)).to_logic(self)
-       end
-
-       # Center the `display` on the world `pos`
-       fun center_on(display: Display, pos: Pos)
-       do
-               self.dx = pos.x - display.width.to_f * 0.5 / basic_zoom
-               self.dy = pos.y - display.height.to_f * 0.5 / basic_zoom
-       end
-end
-
-redef class App
-
-       # Collection of assets
-       var assets = new Assets is lazy
-
-       redef fun on_create
-       do
-               super
-               maximum_fps = 60.0
-               assets.assign_images_to_story context.game.story
-       end
-
-       # Camera managing transformation between world and screen positions
-       var camera = new Camera
-
-       # Square of the minimum distance from the tank for an object to be "far"
-       #
-       # This value influences which sounds are heard,
-       # the strength of vibrations and
-       # whether an arrow points to a far unit
-       private var far_dist2 = 2000.0
-
-       redef fun context
-       do
-               var s = super
-               if s isa RemoteGameContext then maximum_fps = 0.0
-               return s
-       end
-
-       # Tank tracks tracks on the ground
-       #
-       # TODO use particles or at least optimize drawing
-       var tracks = new List[Couple[Pos, Float]]
-
-       redef fun frame_core(display)
-       do
-               var clock = new Clock
-
-               var turn = context.do_turn
-               sys.perfs["do_turn"].add clock.lapse
-
-               # Draw
-
-               # Update camera
-               if down_keys.has("left") then camera.dx -= 1.0
-               if down_keys.has("right") then camera.dx += 1.0
-               if down_keys.has("up") then camera.dy -= 1.0
-               if down_keys.has("down") then camera.dy += 1.0
-
-               var local_tank = local_tank
-               if local_tank != null then
-                       var tank_speed = local_tank.direction_forwards*local_tank.rule.max_speed
-                       tank_speed = tank_speed.clamp(-0.5, 0.5)
-
-                       var prop_pos = local_tank.pos + local_tank.heading.to_vector(tank_speed * 16.0)
-                       var old_pos = camera.center(display)
-                       var half = old_pos.lerp(prop_pos, 0.02)
-
-                       camera.center_on(display, new Pos(half.x, half.y))
-               end
-
-               # Grass
-               display.clear(0.0, 0.45, 0.0)
-
-               # Past tank tracks
-               for track in tracks do
-                       var pos = track.first.to_screen(camera)
-                       display.blit_rotated(assets.drawing.track, pos.x, pos.y, track.second)
-               end
-
-               # Past blast sites
-               for blast in context.game.world.blast_sites do
-                       var pos = blast.to_screen(camera)
-                       display.blit_centered(assets.drawing.blast, pos.x, pos.y)
-               end
-
-               # Terrain features
-               var tl = (new ScreenPos(0.0, 0.0)).to_logic(camera)
-               var br = (new ScreenPos(display.width.to_f, display.height.to_f)).to_logic(camera)
-               for x in [tl.x.floor.to_i .. br.x.ceil.to_i] do
-                       for y in [tl.y.floor.to_i .. br.y.ceil.to_i] do
-                               var feature = context.game.world[x, y]
-                               if feature != null then
-                                       var pos = feature.pos.to_screen(camera)
-                                       var image = feature.rule.images[feature.image_index]
-                                       display.blit_rotated(image, pos.x, pos.y, feature.angle)
-                               end
-                       end
-               end
-
-               # Tanks
-               for tank in context.game.tanks do
-                       # Add random tracks
-                       if (tank.direction_heading != 0.0 and 40.rand == 0) or
-                          (tank.direction_forwards != 0.0 and 100.rand == 0) then
-
-                               tracks.add new Couple[Pos, Float](tank.pos, tank.heading)
-                               if tracks.length > 1000 then tracks.shift
-                       end
-
-                       # Get the player stencil
-                       var player = tank.player
-                       var stencil = null
-                       if player != null then stencil = assets.drawing.stencils[player.stencil_index]
-
-                       if camera.center(display).dist2(tank.pos) > far_dist2 then
-                               var hw = (display.width/2).to_f
-                               var hh = (display.height/2).to_f
-
-                               var angle = camera.center(display).atan2(tank.pos)
-                               var x = hw + angle.cos * (hw-128.0)
-                               var y = hh + angle.sin * (hh-128.0)
-
-                               var screen_pos = new ScreenPos(x, y)
-                               display.blit_rotated(assets.drawing.arrow, screen_pos.x, screen_pos.y, angle)
-                               if stencil != null then display.blit_rotated(stencil, screen_pos.x, screen_pos.y, angle)
-                               continue
-                       end
-
-                       var screen_pos = tank.pos.to_screen(camera)
-
-                       var damage = tank.rule.max_health - tank.health
-                       damage = damage.clamp(0, tank.rule.base_images.length)
-
-                       var base_image = tank.rule.base_images[damage]
-                       display.blit_rotated(base_image, screen_pos.x, screen_pos.y, tank.heading)
-                       if stencil != null then display.blit_rotated(stencil, screen_pos.x, screen_pos.y, tank.heading)
-                       display.blit_rotated(tank.rule.turret_image, screen_pos.x, screen_pos.y, tank.turret.heading)
-
-                       if debug then
-                               var corners = tank.corners_at(new Couple[Pos, Float](tank.pos, tank.heading))
-                               for c in corners do
-                                       var p = c.to_screen(camera)
-                                       display.blit_centered(assets.drawing.red_dot, p.x, p.y)
-                               end
-                       end
-               end
-
-               # Events
-               for event in turn.events do event.client_react(display, turn)
-
-               # Gather and show some performance stats!
-               sys.perfs["draw"].add clock.lapse
-               if context.game.tick % 300 == 5 then print sys.perfs
-       end
-
-       # Keys currently down
-       #
-       # TODO find a nice API and move up to mnit/gamnit
-       var down_keys = new HashSet[String]
-
-       redef fun input(ie)
-       do
-               var local_tank = local_tank
-               var local_player = context.local_player
-
-               # Quit?
-               if ie isa QuitEvent or
-                 (ie isa KeyEvent and ie.name == "escape") then
-
-                       quit = true
-                       return true
-               end
-
-               # Spawn a new tank?
-               if local_tank == null and local_player != null then
-                       if (ie isa KeyEvent and ie.name == "space") or
-                          (ie isa PointerEvent and ie.depressed) then
-
-                               local_player.orders.add new SpawnTankOrder(local_player)
-                               return true
-                       end
-               end
-
-               if ie isa KeyEvent then
-
-                       # Update `down_keys`
-                       var name = ie.name
-                       if ie.is_down then
-                               down_keys.add name
-                       else if down_keys.has(name) then
-                               down_keys.remove name
-                       end
-
-                       # wasd to move tank
-                       var direction_change = ["w", "a", "s", "d"].has(ie.name)
-                       if direction_change and local_tank != null and local_player != null then
-                               var forward = down_keys.has("w")
-                               var backward = down_keys.has("s")
-                               var left = down_keys.has("a")
-                               var right = down_keys.has("d")
-
-                               # Cancel contradictory commands
-                               if forward and backward then
-                                       forward = false
-                                       backward = false
-                               end
-
-                               if left and right then
-                                       left = false
-                                       right = false
-                               end
-
-                               # Set movement and direction
-                               var move = 0.0
-                               if forward then
-                                       move = 0.5
-                               else if backward then move = -0.5
-
-                               var ori = 0.0
-                               if left then
-                                       ori = -local_tank.rule.max_direction/2.0
-                               else if right then ori = local_tank.rule.max_direction/2.0
-
-                               # Activate to invert the orientation on reverse, (for at @R4p4Ss)
-                               #if backward then ori = -ori
-
-                               # Bonus when only moving or only turning
-                               if not forward and not backward then ori *= 2.0
-                               if not left and not right then move *= 2.0
-
-                               # Give order
-                               local_player.orders.add new TankDirectionOrder(local_tank, ori, move)
-                               return true
-                       end
-               end
-
-               # On click (or tap), aim and fire
-               if ie isa PointerEvent then
-
-                       if ie.pressed and local_tank != null and local_player != null then
-                               var target = (new ScreenPos(ie.x, ie.y)).to_logic(camera)
-                               local_player.orders.add new AimAndFireOrder(local_tank, target)
-                               return true
-                       end
-               end
-
-               return false
-       end
-end
-
-redef class TEvent
-       fun client_react(display: Display, turn: TTurn) do end
-end
-
-redef class ExplosionEvent
-       redef fun client_react(display, turn)
-       do
-               var pos = pos.to_screen(app.camera)
-               display.blit_centered(app.assets.drawing.explosion, pos.x, pos.y)
-       end
-end
-
-redef class OpenFireEvent
-       redef fun client_react(display, turn)
-       do
-               var screen_pos = tank.pos.to_screen(app.camera)
-               display.blit_rotated(app.assets.drawing.turret_firing, screen_pos.x, screen_pos.y, tank.turret.heading)
-
-               if tank.pos.dist2(app.camera.center(display)) < app.far_dist2 then
-                       # Within earshot
-                       app.assets.turret_fire.play
-               end
-       end
-end
-
-redef class TurretReadyEvent
-       redef fun client_react(display, turn)
-       do
-               if tank.pos.dist2(app.camera.center(display)) < app.far_dist2 then
-                       # Within earshot
-                       app.assets.turret_ready.play
-               end
-       end
-end
diff --git a/contrib/tinks/src/client/controls.nit b/contrib/tinks/src/client/controls.nit
deleted file mode 100644 (file)
index c3a186f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# On-screen alternative controls
-module controls
-
-import client
-
-redef class App
-
-       # All active UI controls
-       fun controls: Array[Control] is abstract
-
-       redef fun frame_core(display)
-       do
-               super
-
-               for control in controls do control.draw(display)
-       end
-
-       redef fun input(event)
-       do
-               for control in controls do
-                       var hit = control.input(event)
-                       if hit then return true
-               end
-
-               return super
-       end
-end
-
-# An event raised by a `Control`
-class ControlEvent
-       super InputEvent
-
-       # Sender control
-       var sender: Control
-end
-
-# UI control
-abstract class Control
-
-       # Draw `self` to `display`
-       fun draw(display: Display) do end
-
-       # Intercept and act upon events concerving `self`
-       fun input(event: InputEvent): Bool do return false
-end
diff --git a/contrib/tinks/src/client/linux_client.nit b/contrib/tinks/src/client/linux_client.nit
deleted file mode 100644 (file)
index 5e7cca4..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# GNU/Linux client with config saved to `config.json`
-module linux_client
-
-import mnit::linux
-import linux::audio
-import json
-
-import client
-
-# Configuration of the client
-class ClientConfig
-       serialize
-
-       # Resolution width
-       var res_x = 1920 is lazy
-
-       # Resolution height
-       var res_y = 1080 is lazy
-
-       # Should the client play sounds?
-       var play_sounds = true is lazy
-end
-
-redef class App
-       private var config_path: String = sys.program_name.dirname / "../config.json"
-
-       private var config: ClientConfig do
-               if config_path.file_exists then
-                       var content = config_path.to_path.read_all
-                       var deser = new JsonDeserializer(content)
-                       var cc = deser.deserialize
-
-                       if cc == null then
-                               print_error "Client Error: Deserializing config file failed with {deser.errors.join(", ")}"
-                       else if not cc isa ClientConfig then
-                               print_error "Client Error: Deserializing config file failed, got '{cc}'"
-                               # TODO simplify the previous lines with ? or similar
-                       else return cc
-               end
-
-               # Save the default config to pretty Json
-               var cc = new ClientConfig
-               var json = cc.serialize_to_json(plain=true, pretty=true)
-               json.write_to_file config_path
-
-               return cc
-       end
-end
-
-redef class Display
-       redef fun wanted_width do return app.config.res_x
-       redef fun wanted_height do return app.config.res_y
-end
-
-redef class Sound
-       redef fun play do if app.config.play_sounds then super
-end
-
-redef class JsonDeserializer
-       # The only class we deserialize from pretty Json is ClientConfig
-       redef fun class_name_heuristic(object) do return "ClientConfig"
-end