기본 콘텐츠로 건너뛰기

9월, 2016의 게시물 표시

RxJS 에서 GameScene 을 구현하고 있다.

결과물은 여기에
http://jsbin.com/wuhega/edit?js,output

Reactive Programming 의 장점+효용이 극대화되는 분야는 아무래도 게임이지 않을까 싶어서 짬을 내어 RxJS로 슈팅게임을 만들고 있다.

배경+플레이어+총알: https://jsbin.com/worewow/edit?js,output1+적+폭파에니메이션: https://jsbin.com/modedic/edit?js,output2+coffee+적 움직임등 : https://jsbin.com/yobuka/ 대략, 이런 흐름으로 살을 조금씩 붙여가면서 올리고 있는데 어느정도 튜토리얼을 만들려는 생각으로 ECMA6를 가지고 시작을 했지만 {}, (), [] 괄호노동을 통한 손목터널증후근과 코딩하는 시간 만큼 쌍 맞추는 시간이 소모되는 자신을 발견하고 개인의 행복을 위해(...) 다시 coffeescript로 바꿔서 진행하고 있다. 살 것 같다. 아효.
아마도 곧 합쳐질 것 같지만 어느정도 내용물이 만들어졌으니 이것들을 감싸는 껍데기를 어떻게 만들지 코드를 짜면서 고민해보았다.
일단 크게 나누어 보기를 Splash Scene - 한번만 노출. 게임명과 제작자에 대해 알리는 화면Title Scene - 게임시작을 위해 대기하는 화면Game Scene - 실제 게임 화면GameOver Scene - 게임을 더 이상할 수 없는 상황. 이정도로 잡고 1>2>3>4>2>... 의 반복 구조로 설계를 해보기로 했다.
아무런 레퍼런스도 없고 검색해 본 것도 없어서 매우 삽질이 예상되지만 그래도 FRP(Functional Reactive Programming)원칙에 충실하려고 노력했다.
먼저, 화면을 준비한다. 'use strict'
### setup canvas ###
c = document.createElement 'canvas'
document.body.style.margin = 0
document.body.style.height …

Rx 에서 drag and drop 구현.

http://jsbin.com/geqige/edit?js,console,output
선 소스.
( 조금 더 자세한 구현 : http://jsbin.com/ziraga/edit?html,js,output)

먼저 Drag and Drop이라는게 어떤 절차인지 생각해보면
이동하고자 하는 대상에 MouseDown이동하고자 하는 지점까지 MouseMove이동하고자 하는 지점에서 MouseUp 하는 세개의 동작을 순서대로 실행하는 것이라 할 수 있겠다.
100,100 위치에 있는 A라는 대상을 200,200까지 Drag and Drop을 하는 과정을 표로 옮기면

시간(seq)행동좌표1mousedown(150,150)2mousemove(150,150)3mousemove(160,160)4mousemove(170,170)5mousemove(..., ...)(n-1)thmousemove(250, 250)(n)thmouseup(250, 250)
과 같은 과정을 수행할 것이다.
눈치챘을지도 모르겠지만 mousemove 구간이 바로 Stream이다!
Rx 기준으로 그러면 다시 Drag and Drop을 재정의하면
mousedown 이후 시점으로부터 mouseup이 되기전까지 mousemove 를 Observe 하는 것 인것이다.

그러면 재료를 모아보자.

mousedown
mouseup
mousemove
이 세 개를 Observable 로 만들자.

  const down$ = Rx.Observable.fromEvent(box, 'mousedown');
  const move$ = Rx.Observable.fromEvent(document, 'mousemove');
  const up$ = Rx.Observable.fromEvent(document, 'mouseup');
별거 없다. 이게 전부.
move$랑 up$은 왜 box가 아닌가 싶은데 실제로 순간 움직임이 box의 범위를 넘어갈 수도 있기 때문에 document 전체와 바인딩하는 편이 좋…

spectrum 에게 물어보세요. multiple option을 flat 하게 하고 싶어요.

질문:
쇼핑몰에서 옵션이 여러개 있는데 이걸 조합해서 보여주고 싶어요.
사이즈: s, m, l
색상: blue, red
길이: short, long
대상: girl, boy, woman, man

이라고 했을 때
s blue short woman
이런 식으로요.

답변:
reduce 를 사용하세요.
풀이 예제 << 클릭하면 coffee/js 소스랑 결과값 모두 볼 수 있어요.

Array::flatMap = (lambda) ->
  @concat.apply [], @.map lambda
v=[
 ['s','m','l']
 ['blue','red']
 ['short', 'long']
 ['girl', 'boy', 'woman', 'man']
]
console.log "result\n",
  v.reduce (x1,x2)->
    x1.map (o)->
      x2.map (p)->
        "#{o} #{p}"
    .flatMap (o)->o 분류의 갯수는 상관없어요. 두개를 순서대로 합쳐야한다! 싶을 때는 reduce로 어떻게 해봐야지! 하고 시작하는게 좋아요.
먼저 ['s', 'm', 'l'] 하고 ['blue', 'red'] 만 놓고 보자구요. map으로 이중 루프를 돌면서 둘을 조합하면 되겠지요? ['s', 'm', 'l'].map (o)->
  ['blue', 'red'].map (p)->
    "#{o} #{p}" 근데 이렇게 하면 [["s blue","s red"],["m blue","m red"],[…

SVG의 path tag 에 대해 araboja

시작은 SVG에서 호(弧:arc)를 그리는 것에서 비롯하였다.
SVG는 정비율 원인 circle 과 ellipse는 있는데 arc 가 따로 있는 건 아니다.
pie graph 류를 그릴 땐 꼭 필요한데 path 말곤 뾰족한 수가 없어 보인다.

뭐 이렇게 된거 path 에 대해 전부 다 알아보도록 하자.

path는 "명령 숫자 숫자 ..."의 조합인데 각각 의도에 맞는 명령(M,L,H,V,Z,C,S,Q,T,A)와 거기에 맞는 인자들을 잘 넣어서 한방에 그릴 수 있게 한다.
참고로, 각각의 커맨드를 소문자로 쓰면 상대 좌표계로 바뀐다. 인자가 없는 Z의 경우는 어느쪽이던 똑같다.
그냥 생각해봐도 일일이 line 으로 모든 걸 다 그리는 건 비효율적이긴 하다.
어짜피 이런 건 아는 것 보다 "하는" 것이 중요하니까 한번 직접 크롬 개발 환경이라도 열고 해보는 게 좋다.


이동 명령 (M)직선 명령 (L, H, V)L x y - 현재 점에서 x,y 까지 직선을 긋는다.H x - 현재 점에서 x 위치까지 가로로 직선을 긋는다.V y - 현재 점에서 y 위치까지 세로로 직선을 긋는다.폐쇄 명령 (Z) - 맨 처음 점으로 되돌아가게끔 직선을 그어 닫힌 면을 만든다.
인자 없는 것이 특징.곡선명령 (C,S,Q,T)C x1 y1, x2 y2, x y - 현재 점에서 x,y 까지 직선을 그은 것을 Bezier 곡선을 만든다. 현재 점에서 x1,y1만큼, x,y 에서 x2,y2 만큼 핸들을 사용한다.
c 즉 상대좌표일 때 주의할 점은 x2 y2는 x,y 기준이 아니라 현재 점 기준.S x2, y2, x y - 이전의 핸들을 연장한다. 아래의 경우를 비교해보자. 둘은 완전히 같은 형태의 곡선을 그리지만 S를 쓰는 쪽이 인자가 하나 적다.
<path d="M100 500 C 150 400, 200 500, 200 500 C 250 600, 300 500, 300 500"/>
<path d="M100 600 C 15…

openshift 에 nodebb 를 올려보자.

rhc 그러니까 옛날 버전 기준이다.
요즘껀 도대체 뭐가 뭔지 모르겠어. 잊지 않겠다 Kubernetes.. o><

rhc app create --no-scaling nodebb https://raw.githubusercontent.com/icflorescu/openshift-cartridge-nodejs/master/metadata/manifest.yml

rhc cartridge add https://raw.githubusercontent.com/icflorescu/openshift-cartridge-mongodb/master/metadata/manifest.yml -a nodebb

https://github.com/icflorescu/openshift-cartridge-nodejs/issues/55
참조.
node.js 버전을 지정하려면 semver.io를 참조. NODE_VERSION_URL 환경 변수도 바꿔줘야한다.
rhc env set -a [어플리케이션 이름] NODE_VERSION_URL=https://semver.io/node/resolve/4
(https://semver.io/node 가 안정버전, https://semver.io/node/unstable 이 최신이다)
일단, NODE_VERSION_URL 을 지정하지 않았으므로 최신(unstable) node.js 설치를 할거다.
app create를 하면 nodebb 디렉토리를 만드는데
cd nodebb git remote add upstream -m master https://github.com/NodeBB/NodeBB.git rm -rf `ls` .eslintrc && git commit -a -m 'Cleaned up for NodeBB' git pull --no-edit -s recursive -X theirs upstream master
순으로 하자. upstream에서 가져올 때 master 로 했는데 원래는 v0.9.x 까지가 권장사항.
g…

외부에서 REST로 Meteor 서버에 접근할 때 인증(Authentication) 팁 - Picker 사용

Meteor 서버와 외부 서버끼리 연동할 일이 간혹 있다.
혹은, 정적 웹페이지를 구축하고 REST로 Meteor 서버에 접근하고 싶을 수도 있을 것이다.

가령 /image 라는 경로에 POST로 그림 파일을 올리고자 하면 클라이언트 쪽에서 보내는 것은 문제가 아니지만 사용자를 어떻게 인증할 것인가에 대한 문제가 생긴다.

그렇다고 매번 POST를 보낼 때 마다 사용자 아이디와 패스워드를 올려서 검증하는 것도 번거로울 뿐만 아니라 보안상 좋지 않다.
Meteor 의 경우 최초 사용자 인증이 끝나면 loginToken이라는 값을 반환하여 이 값으로 다음번에 인증을 할 수 있는데 이것은 사용자 계정 정보

curl -XPOST 'localhost:3000/image' -H "x-user-auth:<지난번 로그인 때 저장한 loginToken>" -F "image=@/xxx/xxx/xxx/xxx.gif"

로 호출한다고 가정했을때
POST에 대한 filter 를 설정하고
API=
  GET: Picker.filter (req, res)-> req.method is "GET"
  POST: Picker.filter (req, res)-> req.method is "POST"
  DELETE: Picker.filter (req, res)-> req.method is "DELETE" 서버 라우팅을 해준다. API.POST.route '/image', (params, req, res)->
  token = req.headers['x-user-auth']
  hashedToken = Accounts._hashLoginToken(token)
  user = Meteor.users.findOne 'services.resume.loginTokens.hashedToken': hashedToken
  check user, …

ReactiveX / RxJS - 상태(State)에 대한 두 가지 접근

RxJS, BaconJS, Highland, 등등 정말 Stream 전성시대. FRP(Functional Reactive Programming)가 흥하는 시대를 살고 있는 느낌이다.
기존의 Array에 람다 함수들에 시간 개념이 들어간 정도인데 그렇다면 데이터가 이렇게 흘러가고 있다면 어떻게 상태가 변할때 마다 표현할지 고민하는데
그걸 State Store 라는 걸 사용해서 상태의 변화를 Reduce (Rx에선 scan) 하여 반영한다.

가령 기존의 Control Flow 기반 프로그래밍에선
1. 상태 변수를 생성한다.
2. 이벤트가 발생한다.
3. 이벤트 콜백을 실행하여 상태 변수를 갱신한다.
4. 상태 변수를 UI에 반영한다.
였다면

RxJS같은 Data Flow 기반 프로그래밍에선
1. 이벤트를 발행한다.
2. 이벤트를 상태 변화로 변환(map)한다.
3. 2를 reduce 한 스트림을 구독한다.
4. 3의 스트림이 발생할 때마다 UI에 반영한다.
정도의 차이라고 볼 수 있겠다.

그러니까 오늘의 나는 태어날 때의 나부터 어제의 나까지를 리듀스 한 것이라고 (.....)

... 같은 건 없다.
(출처: twitter)
http://jsbin.com/bowumar 에 클릭 카운터를 구현해보았다.

let $=(e=>document.querySelector(e));
let approach1=()=>{
  let clickStream=new Rx.BehaviorSubject(0);
  $("#inc").addEventListener('click',e=>clickStream.next(1));
  $("#dec").addEventListener('click',e=>clickStream.next(-1));
  clickStream.scan((x,y)=>x+y).subscribe(o=>$("#counter").innerText=o);
};
let approac…