Play Squash with Ruby, OpenGL, and a Wiimote - ShRUG Feb 2011
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Play Squash with Ruby, OpenGL, and a Wiimote - ShRUG Feb 2011

on

  • 3,337 views

Using the Ruby programming language, the CWiid library, and the Ruby bindings for OpenGL, it is possible to develop a 3D game which is controlled using a Nintendo Wii Remote. By furthermore invoking ...

Using the Ruby programming language, the CWiid library, and the Ruby bindings for OpenGL, it is possible to develop a 3D game which is controlled using a Nintendo Wii Remote. By furthermore invoking RMagick and the ALSA library, one can add textures and sound to the game. Note that the library for accessing the Wii Remote (CWiid) and the sound library (ALSA) require Linux. However it is conceivable to do a similar project with alternate libraries on another operating system.

Also see http://www.wedesoft.demon.co.uk/shrug15.html

Statistics

Views

Total Views
3,337
Views on SlideShare
3,336
Embed Views
1

Actions

Likes
0
Downloads
6
Comments
0

1 Embed 1

https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Play Squash with Ruby, OpenGL, and a Wiimote - ShRUG Feb 2011 Presentation Transcript

  • 1. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Play Squash with Ruby, OpenGL, and a Wiimote Play Squash with Ruby, OpenGL and a Wiimote Jan Wedekind Mon Feb 14 19:00:00 BST 2011c 2011 Jan Wedekind 1/29
  • 2. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Golf Simulator Outland Movie scene from “Outland”c 2011 Jan Wedekind 2/29
  • 3. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Golf Simulator TM High Definition Golf Golf Simulator (using high-speed cameras?)c 2011 Jan Wedekind 3/29
  • 4. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Sony PS3 Move Bluetooth device • 8 buttons ( , ◦, ×, , Select, Home, Move) • Analog trigger • Sphere illuminated by RGB LED for external motion tracking • 3-axis accelerometer • 3-axis gyroscope • magnetometerc 2011 Jan Wedekind 4/29
  • 5. http://vision.eng.shu.ac.uk/jan/shrug15.pdf PS3 Move E3 Tech Demo Also see http://howtohackps3.com/playstation-move-new-tech-demo-video-tour/c 2011 Jan Wedekind 5/29
  • 6. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Sony EyeToy Sega Virtua Fighter for EyeToy Webcamc 2011 Jan Wedekind 6/29
  • 7. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Microsoft Kinect Also see http://www.primesense.com/c 2011 Jan Wedekind 7/29
  • 8. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Camspace Webcam instead of Game Controllerc 2011 Jan Wedekind 8/29
  • 9. http://vision.eng.shu.ac.uk/jan/shrug15.pdf The Nintendo Wii Remote (Wiimote) Bluetooth device • 11 buttons (1, 2, A, B, +, -, Home, ⇐, ⇒, ⇑, ⇓) • 4 LEDs • rumble motor • 3-axis accelerometer • IR camera and chip for detecting 5 brightest dots • speaker • expansion portc 2011 Jan Wedekind 9/29
  • 10. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Wii E3 Tech Democ 2011 Jan Wedekind 10/29
  • 11. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Wiimote Whiteboard by Johnny Chung Lee IR pen Wiimote stand 4 point calibration ⇒ Wiimote Whiteboard See http://johnnylee.net/projects/wii/c 2011 Jan Wedekind 11/29
  • 12. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Cwiid library #include <cwiid.h> #include <stdio.h> int main(void) // gcc -o wii wii.c -lcwiid { cwiid wiimote t *wiimote; struct cwiid state state; bdaddr t any = { { 0, 0, 0, 0, 0, 0 } }; wiimote = cwiid open( &any, 0 ); cwiid set rpt mode( wiimote, CWIID RPT BTN | CWIID RPT ACC ); do { cwiid get state( wiimote, &state ); printf( "{ %3d, %3d, %3d }n" , state.acc[0], state.acc[1], state.acc[2] ); usleep( 10000 ); } while ( ( state.buttons & CWIID BTN A ) == 0 ); cwiid close( wiimote ); return 0; } See http://abstrakraft.org/cwiid/ for Cwiid library See http://wiibrew.org/wiki/Wiimote/Library for other librariesc 2011 Jan Wedekind 12/29
  • 13. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Cwiid Ruby Gem require ’cwiid’ # ruby -rrubygems wii.rb wiimote = WiiMote.new wiimote.rpt mode = WiiMote::RPT BTN | WiiMote::RPT ACC begin wiimote.get state puts "[ %3d, %3d, %3d ]" % wiimote.acc end until ( wiimote.buttons & WiiMote::BTN A ) != 0 wiimote.close See https://github.com/wedesoft/cwiid/ for Cwiid Ruby Gemc 2011 Jan Wedekind 13/29
  • 14. http://vision.eng.shu.ac.uk/jan/shrug15.pdf OpenGL with Ruby require ’opengl’ # http://ruby-opengl.rubyforge.org/ display = proc do GL.Clear GL::COLOR BUFFER BIT | GL::DEPTH BUFFER BIT GL.Material GL::FRONT, GL::DIFFUSE, [ 0.2, 1.0, 0.2, 1.0 ] GLUT.SolidSphere 1.0, 16, 16 GLUT.SwapBuffers end reshape = proc do |w, h| GL.Viewport 0, 0, w, h GL.MatrixMode GL::PROJECTION GL.LoadIdentity GLU.Perspective 60.0, w.to f / h, 1.0, 20.0 GL.MatrixMode GL::MODELVIEW GL.LoadIdentity GL.Translate 0.0, 0.0, -2.5 end GLUT.Init GLUT.InitDisplayMode GLUT::DOUBLE | GLUT::RGB | GLUT::DEPTH GLUT.CreateWindow ’Sphere’ GL.Light GL::LIGHT0, GL::POSITION, [ 0.5, 0.5, 1.0, 0.0 ] GL.Enable GL::LIGHTING GL.Enable GL::LIGHT0 GL.Enable GL::DEPTH TEST GLUT.DisplayFunc display GLUT.ReshapeFunc reshape GLUT.MainLoopc 2011 Jan Wedekind 14/29
  • 15. http://vision.eng.shu.ac.uk/jan/shrug15.pdf OpenGL with Ruby Also see “Red Book”: http://vision.eng.shu.ac.uk/jan/redbook.pdf Ruby OpenGL Gem comes with code examplesc 2011 Jan Wedekind 15/29
  • 16. http://vision.eng.shu.ac.uk/jan/shrug15.pdf GLUT Framework require ’opengl’ $list = nil def init $list = GL.GenLists 1 GL.NewList $list, GL COMPILE GL.EndList end display = proc do GL.Clear GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT GL.CallList $list GLUT.SwapBuffers end reshape = proc { |w, h| } keyboard = proc { |key, x, y| } animate = proc { GLUT.PostRedisplay } GLUT.Init GLUT.InitDisplayMode GLUT DOUBLE | GLUT RGB | GLUT DEPTH GLUT.InitWindowSize 640, 480 GLUT.CreateWindow ’Test’ init GLUT.DisplayFunc display GLUT.ReshapeFunc reshape GLUT.KeyboardFunc keyboard GLUT.IdleFunc animate GLUT.MainLoopc 2011 Jan Wedekind 16/29
  • 17. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Quadruple of Vertices # ... def init $list = GL.GenLists 1 GL.NewList $list, GL COMPILE GL.Begin GL::QUADS GL.Normal 0.0, 1.0, 0.0 GL.Vertex -1.0,-1.0, 0.0 GL.Vertex 1.0,-1.0, 0.0 GL.Vertex 1.0, 1.0, 0.0 GL.Vertex -1.0, 1.0, 0.0 GL.End GL.EndList end display = proc do GL.Clear GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT GL.PushMatrix GL.Rotate -60.0, 1.0, 0.0, 0.0 GL.CallList $list GL.PopMatrix GLUT.SwapBuffers end # ...c 2011 Jan Wedekind 17/29
  • 18. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Quadruple of Verticesc 2011 Jan Wedekind 18/29
  • 19. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Texture Mapping # ... def init $tex = GL.GenTextures 1 image = Magick::Image.read( ’ruby.png’ ).first GL.BindTexture GL::TEXTURE 2D, $tex[0] GL.TexParameter GL::TEXTURE 2D, GL::TEXTURE MIN FILTER, GL::NEAREST GL.TexImage2D GL::TEXTURE 2D, 0, GL::RGB, image.columns, image.rows, 0, GL::RGB, GL::UNSIGNED BYTE, image.export pixels to str( 0, 0, image.columns, image.rows, ’RGB’ , Magick::CharPixel ) $list = GL.GenLists 1 GL.NewList $list, GL COMPILE GL.Enable GL::TEXTURE 2D GL.Material GL::FRONT, GL::AMBIENT, [ 1.0, 1.0, 1.0, 1.0 ] GL.BindTexture GL::TEXTURE 2D, $tex[0] GL.Begin GL::QUADS GL.Normal 0.0, 1.0, 0.0 GL.TexCoord 0.0, 1.0; GL.Vertex -1.0,-1.0, 0.0 GL.TexCoord 1.0, 1.0; GL.Vertex 1.0,-1.0, 0.0 GL.TexCoord 1.0, 0.0; GL.Vertex 1.0, 1.0, 0.0 GL.TexCoord 0.0, 0.0; GL.Vertex -1.0, 1.0, 0.0 GL.End GL.Disable GL::TEXTURE 2D GL.EndList end # ...c 2011 Jan Wedekind 19/29
  • 20. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Texture Mappingc 2011 Jan Wedekind 20/29
  • 21. http://vision.eng.shu.ac.uk/jan/shrug15.pdf ALSA require ’hornetseye alsa’ include Hornetseye RATE = 48000 CHANNELS = 2 LEN = RATE / 400 output = AlsaOutput.new ’default:0’ , RATE, CHANNELS sine = lazy( CHANNELS, LEN ) do |i,j| Math.sin( 2 * Math::PI * j / LEN ) * 32767 end.to sint ( 3 * RATE / LEN ).times { output.write sine } output.drain 40000 sin(2*pi*x/48000*400)*32767 30000 20000 10000 0 -10000 -20000 -30000 -40000 0 200 400 600 800 1000 1200 tc 2011 Jan Wedekind 21/29
  • 22. http://vision.eng.shu.ac.uk/jan/shrug15.pdf WAV Files require ’hornetseye alsa’ include Hornetseye RATE = 11025 CHANNELS = 1 def wav( file name ) str = File.new( file name, ’rb’ ).read[ 44 .. -1 ] malloc = Malloc.new str.size malloc.write str MultiArray( SINT, CHANNELS, malloc.size / ( 2 * CHANNELS ) ).new malloc end output = AlsaOutput.new ’default:0’ , RATE, CHANNELS output.write wav( ’forest.wav’ ) output.drainc 2011 Jan Wedekind 22/29
  • 23. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Squash Karim Darwish vs Gregory Gaultierc 2011 Jan Wedekind 23/29
  • 24. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Bouncing Ball # ... G = 9.81; F = 0.8; R = 0.3 $y = 2; $vy = 0; $t = Time.new.to f display = proc do GL.Clear GL::COLOR BUFFER BIT | GL::DEPTH BUFFER BIT GL.PushMatrix GL.Material GL::FRONT, GL::DIFFUSE, [ 0.2, 1.0, 0.2, 1.0 ] GL.Translate 0.0, $y, 0.0 GLUT.SolidSphere R, 16, 16 GL.PopMatrix GLUT.SwapBuffers end animate = proc do ∆t = ti+1 − ti dt = Time.new.to f - $t xi+1 = xi + vi ∆t + 1 ai ∆t2 2 $t += dt $vy -= G * dt vi+1 = vi  ai ∆t  + $y += ( $vy - 0.5 * G * dt ) * dt 0 if $y < R         ai = −g $y = 2 * R - $y     $vy = -F * $vy         end       GLUT.PostRedisplay 0 end # ...c 2011 Jan Wedekind 24/29
  • 25. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Strike: Strength and Time require ’hornetseye alsa’ require ’cwiid’ include Hornetseye RISING = 20.0; FALLING = 0.0; DELAY = 0.5 s = File.new( ’racket.wav’ , ’rb’ ).read[ 44 .. -1 ] m = Malloc.new s.size; m.write s racket = MultiArray( SINT, 2, m.size / 4 ).new m wiimote = WiiMote.new output = AlsaOutput.new wiimote.rpt mode = WiiMote::RPT BTN | WiiMote::RPT ACC sign = nil; strength = 0.0; delay = Time.new.to f begin wiimote.get state acc = wiimote.acc.collect { |x| ( x - 120.0 ) / 2.5 } if acc[2].abs >= RISING and Time.new.to f >= delay sign = acc[2] > 0 ? +1 : -1 unless sign strength = [ acc[2].abs, strength ].max elsif sign if acc[2] * sign <= FALLING output.write( ( racket * ( strength / 120.0 ) ).to sint ) puts "strength = #{strength}" sign = nil; strength = 0.0; delay = Time.new.to f + DELAY end end end until wiimote.buttons == WiiMote::BTN Bc 2011 Jan Wedekind 25/29
  • 26. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Constraintsc 2011 Jan Wedekind 26/29
  • 27. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Constraintsc 2011 Jan Wedekind 27/29
  • 28. http://vision.eng.shu.ac.uk/jan/shrug15.pdf Democ 2011 Jan Wedekind 28/29
  • 29. http://vision.eng.shu.ac.uk/jan/shrug15.pdf TODO • OpenGL shadows • scoring system • player visualisation • multiplayer • better physics (Runge-Kutta integration) • ...c 2011 Jan Wedekind 29/29