GlovePIE:ZSNES - Smash TV

From WiiLi

Jump to: navigation, search

The following is an algorithm for The Smash TV written with GlovePIE. The control is mapped for ZSNES and support IR sensor and DPad to shot.

Contents

[edit] Nunchuk

The Nunchuk is mandatory to control the character. The DPad is reserved for alternative shooting.

[edit] IR Sensor

This script split the screen in 9 zones, the first 8 represents each directions and diagonals for shooting, the center is split again in four portions mapped on diagonals for quick turnover.

To shot, aim at the screen and press A or B.

(A virtual cursor is always indicating where you aim.)

A representation of each fire zones
A representation of each fire zones

[edit] Traditional DPAD

If you're not confortable with the IR mode, the DPAD is also mapped for shooting.

[edit] Classic controller

If you want a script for Smash TV and the Classic controller [Classic Controller Script]

// Smash TV (for ZSNES)
// Created by Marc-Andre Larouche
// marclar83@gmail.com
//
// 2 fire modes: {IR mode, DPAD}
// Version 0.2
//
// *The Nunchuk is mandatory.
//
// To shot, aim the virtual cursor to one of the extremity of the screen and
// press A or B to shot. You can also use the DPAD as well.
// August 2007

/*********************************************

   Displacement:
    Nunchuck: Thumbstick

   Select/Start:
    Select:
     Minus
    Start:
     Plus

   Fast Foward:
     Home

********************************************/
   Key.Z = Wiimote.Down
   Key.X = Wiimote.Right
   Key.A = Wiimote.Left
   Key.S = Wiimote.Up
   Key.D = Wiimote.Nunchuk.CButton
   Key.C = Wiimote.Nunchuk.ZButton
   Key.Enter = Wiimote.Plus
   Key.Space = Wiimote.Minus
   Key.Console = Wiimote.Home

   Key.left = Wiimote.Nunchuk.JoyX <= -25%
   Key.right = Wiimote.Nunchuk.JoyX >= 25%
   Key.up = Wiimote.Nunchuk.JoyY <= -25%
   Key.down = Wiimote.Nunchuk.JoyY >= 25%

wiimote.LED1 = true;
wiimote.LED2 = false;
wiimote.LED3 = false;
wiimote.LED4 = false;

   //Fire in the direction of your cursor in relation with the center of the screen.
   if Wiimote.A == true or Wiimote.B == true  then
         var.active = true;
           if var.dir_left == true and var.prevY != "left" then
              var.prevY = "left";
              Key.A = true;
           else
              var.prevY = "";
              Key.A = false;
           end if
           if var.dir_right == true and var.prevY != "right" then
              var.prevY = "right";
              Key.X = true;
           else
              var.prevY = "";
              Key.X = false;
           end if
           if var.dir_up == true and var.prevX != "up" then
              var.prevX = "up";
              Key.S = true;
           else
              var.prevX = "";
              Key.S = false;
           end if
           if var.dir_down == true and var.prevX != "down" then
              var.prevX = "down";
              Key.Z = true;
           else
              var.prevX = "";
              Key.Z = false;
           end if
   end if
    // on btn release
    if Wiimote.A != true and Wiimote.B != true and var.active == true then
       var.active = false;
       var.prevX = "";
       var.prevY = "";
       Key.Z = false;
       Key.X = false;
       Key.A = false;
       Key.S = false;
    end if

     // Indicate in which portion of the screen you aim with the virtual cursor.
     if (var.SmoothX * Screen.Width)<= var.screenPortionWidth then
        var.dir_left = true;
     else
        var.dir_left = false;
     end if

     if (var.SmoothX * Screen.Width)>= var.screenPortionWidth*2 then
        var.dir_right = true;
     else
        var.dir_right = false;
     end if

     if (var.SmoothY * Screen.Height)<= var.screenPortionHeight then
        var.dir_up = true;
     else
        var.dir_up = false;
     end if

     if (var.SmoothY * Screen.Height)>= var.screenPortionHeight*2 then
        var.dir_down = true;
     else
        var.dir_down = false;
     end if

     // We had split the screen in 9 portions, the firsts 8 are easy to assign,
     // but the middle is split again in four diagonals for more accuracy.
     if (var.SmoothX * Screen.Width)>= var.screenPortionWidth and (var.SmoothX * Screen.Width)<= var.screenPortionWidth*2 and (var.SmoothY * Screen.Height)>= var.screenPortionHeight and (var.SmoothY * Screen.Height)<= var.screenPortionHeight*2 then
        if (var.SmoothX * Screen.Width)<= var.screenPortionWidth+(var.screenPortionWidth/2)  then
           var.dir_left = true;
        else
           var.dir_left = false;
        end if
        if (var.SmoothX * Screen.Width)>= var.screenPortionWidth+(var.screenPortionWidth/2) then
           var.dir_right = true;
        else
           var.dir_right = false;
        end if

        if (var.SmoothY * Screen.Height)<= var.screenPortionHeight+(var.screenPortionHeight/2) then
           var.dir_up = true;
        else
           var.dir_up = false;
        end if

        if (var.SmoothY * Screen.Height)>= var.screenPortionHeight*2+(var.screenPortionHeight/2) then
           var.dir_down = true;
        else
           var.dir_down = false;
        end if
     end if

// I'm using Carl Kenner: "My best IR Mouse Script, with 5DOF Tracking" to handle the IR sensors.
// I had tweaks the cursor motions for the purpose of this script.

var.screenPortionWidth = Screen.Width/3;
var.screenPortionHeight = Screen.Height/3;
var.SensorBarSeparation = 7.5 inches  // distance between middles of two sensor bar dots
var.NoYawAllowed = true  // Calculates X if no yaw is allowed, otherwise calculates Yaw but not X
var.IRMulX = 1.2
var.IRMulY = 1.2
var.IROffsetX = 0  // add to mouse.x
var.IROffsetY = 0  // add to mouse.y
var.IRLeftButton = Wiimote.A
var.IRRightButton = Wiimote.B

// Compensate for roll
var.c = cos(Smooth(wiimote.roll, 10))
var.s = sin(Smooth(wiimote.roll, 10))
if wiimote.dot1vis then
  var.dot1x = var.c*(511.5-wiimote.dot1x)/511.5 - var.s*(wiimote.dot1y-383.5)/511.5
  var.dot1y = var.s*(511.5-wiimote.dot1x)/511.5 + var.c*(wiimote.dot1y-383.5)/511.5
end if
if wiimote.dot2vis then
  var.dot2x = var.c*(511.5-wiimote.dot2x)/511.5 - var.s*(wiimote.dot2y-383.5)/511.5
  var.dot2y = var.s*(511.5-wiimote.dot2x)/511.5 + var.c*(wiimote.dot2y-383.5)/511.5
end if

// if both dots are visible check which is which and how far apart
if wiimote.dot1vis and wiimote.dot2vis then
  if var.dot1x <= var.dot2x then
    var.leftdot = 1
    var.dotdeltay = var.dot2y - var.dot1y
  else
    var.leftdot = 2
    var.dotdeltay = var.dot1y - var.dot2y
  end if
  var.dotdeltax = abs(var.dot1x-var.dot2x)
  var.DotSep = hypot(var.dotdeltax, var.dotdeltay) * 511.5
  var.IRDistance = var.SensorBarSeparation * 1320 / var.DotSep
end if

// sort out the position of the left and right dots
if var.leftdot = 1 then
  if wiimote.dot1vis and wiimote.dot2vis then
    var.LeftDotX = var.dot1x
    var.LeftDotY = var.dot1y
    var.LeftDotVis = true
    var.RightDotX = var.dot2x
    var.RightDotY = var.dot2y
    var.RightDotVis = true
  else if wiimote.dot1vis then
    if hypot(var.leftdotx-var.dot1x,var.leftdoty-var.dot1y) <= hypot(var.rightdotx-var.dot1x,var.rightdoty-var.dot1y) then
      // is the real dot 1
      var.LeftDotX = var.dot1x
      var.LeftDotY = var.dot1y
      var.RightDotX = var.dot1x + var.dotdeltax
      var.RightDotY = var.dot1y + var.dotdeltay
      var.LeftDotVis = true
      var.RightDotVis = false
    else
      // was originally dot 2, but now called dot 1.
      var.leftdot = 2 // this dot (1) is actually the right dot
      var.LeftDotX = var.dot1x - var.dotdeltax
      var.LeftDotY = var.dot1y - var.dotdeltay
      var.RightDotX = var.dot1x
      var.RightDotY = var.dot1y
      var.RightDotVis = true
      var.LeftDotVis = false
    end if
  else if wiimote.dot2vis then
    var.LeftDotX = var.dot2x - var.dotdeltax
    var.LeftDotY = var.dot2y - var.dotdeltay
    var.RightDotX = var.dot2x
    var.RightDotY = var.dot2y
    var.RightDotVis = true
    var.LeftDotVis = false
  end if
else if var.leftdot = 2 then
  if wiimote.dot1vis and wiimote.dot2vis then
    var.LeftDotX = var.dot2x
    var.LeftDotY = var.dot2y
    var.LeftDotVis = true
    var.RightDotX = var.dot1x
    var.RightDotY = var.dot1y
    var.RightDotVis = true
  else if wiimote.dot1vis then
    if hypot(var.leftdotx-var.dot1x,var.leftdoty-var.dot1y) <= hypot(var.rightdotx-var.dot1x,var.rightdoty-var.dot1y) then
      var.leftdot = 1 // dot 1 is now the left dot
      var.LeftDotX = var.dot1x
      var.LeftDotY = var.dot1y
      var.RightDotX = var.dot1x + var.dotdeltax
      var.RightDotY = var.dot1y + var.dotdeltay
      var.LeftDotVis = true
      var.RightDotVis = false
    else
      // the real dot 1 (on the right)
      var.LeftDotX = var.dot1x - var.dotdeltax
      var.LeftDotY = var.dot1y - var.dotdeltay
      var.RightDotX = var.dot1x
      var.RightDotY = var.dot1y
      var.RightDotVis = true
      var.LeftDotVis = false
    end if
  else if wiimote.dot2vis then
    var.RightDotX = var.dot2x + var.dotdeltax
    var.RightDotY = var.dot2y + var.dotdeltay
    var.LeftDotX = var.dot2x
    var.LeftDotY = var.dot2y
    var.LeftDotVis = true
    var.RightDotVis = false
  end if
else
  var.LeftDotX = var.dot1x
  var.LeftDotY = var.dot1y
  var.RightDotX = var.LeftDotX
  var.RightDotY = var.LeftDotY
  var.LeftDotVis = true
  var.RightDotVis = true
end if


// Find the imaginary middle dot
var.MiddleDotX = (var.leftdotx + var.rightdotx)/2
var.MiddleDotY = (var.leftdoty + var.rightdoty)/2
var.MiddleDotVis = wiimote.dot1vis or wiimote.dot2vis

if var.MiddleDotVis then
  var.TotalPitch = atan2(511.5*var.MiddleDotY,1320) + Wiimote.Pitch
  var.DotYaw = atan2(-511.5*var.MiddleDotX,1320) // assume yaw is 0
  var.WiimoteYawNoX = atan2(511.5*var.MiddleDotX,1320)
  var.WiimoteXNoYaw = -sin(var.dotyaw)*var.IRDistance
  var.WiimoteY = -sin(var.totalpitch)*var.IRDistance
  var.WiimoteZ = (-sqrt(sqr(var.IRDistance) - sqr(var.WiimoteY)))*var.IRDistance/RemoveUnits(var.IRDistance)
end if

// scale it to the screen range 0 to 1
var.IRx = var.IRMulX*var.middledotx/2 + 0.5
var.IRy = var.IRMulY*var.middledoty*1023/767/2 + 0.5
var.IRvis = wiimote.dot1vis or wiimote.dot2vis
var.IROnScreen = 0 <= var.IRx <= 1  and  0 <= var.IRy <= 1

// is it off the screen?
var.IRTooFarLeft = var.IRx < 0 or (var.IRx < 0.1 and (not var.IRvis))
var.IRTooFarRight = var.IRx > 1 or (var.IRx > 1-0.1 and (not var.IRvis))
var.IRTooFarUp = var.IRy < 0 or (var.IRy < 0.1 and (not var.IRvis))
var.IRTooFarDown = var.IRy > 1 or (var.IRy > 1-0.1 and (not var.IRvis))

// Heavily smooth small movements, but do zero lag for quick movements
var.MoveAmount = 1024*hypot(delta(var.IRx), delta(var.IRy))
if smooth(var.MoveAmount) > 12 then
  var.SmoothX = var.IRx
  var.SmoothY = var.IRy
  var.LastSureFrame = PIE.Frame
else if (PIE.frame-var.LastSureFrame) > 18 then
  var.SmoothX = Smooth(var.IRx, 18, 4/1024)
  var.SmoothY = Smooth(var.IRy, 18, 4/1024)
else if (PIE.frame-var.LastSureFrame) > 14 then
  var.SmoothX = Smooth(var.IRx, 14, 4/1024)
  var.SmoothY = Smooth(var.IRy, 14, 4/1024)
else if (PIE.frame-var.LastSureFrame) > 10 then
  var.SmoothX = Smooth(var.IRx, 10, 4/1024)
  var.SmoothY = Smooth(var.IRy, 10, 4/1024)
else if (PIE.frame-var.LastSureFrame) > 6 then
  var.SmoothX = Smooth(var.IRx, 6, 4/1024)
  var.SmoothY = Smooth(var.IRy, 6, 4/1024)
else if (PIE.frame-var.LastSureFrame) > 2 then
  var.SmoothX = Smooth(var.IRx, 2, 4/1024)
  var.SmoothY = Smooth(var.IRy, 2, 4/1024)
end if

// Freeze the mouse cursor while they start pressing the button
// otherwise it will make the cursor jump
var.Freeze = (var.IRLeftButton or var.IRRightButton) and KeepDown(pressed(var.IRLeftButton) or pressed(var.IRRightButton), 600ms)

// This is the only changes I have made to Carl' script
if var.IRvis and (not var.Freeze) then
  Cursor1.Visible = true
  Cursor1.CursorPosX   = var.SmoothX * Screen.Width
  Cursor1.CursorPosY   = var.SmoothY * Screen.Height
end if

Personal tools